Fail the upload of file instead of adding malformed metadata

Mobile app crash

 [DiffFetcher] [SEVERE] [2024-09-14 01:03:33.632159] type 'List<dynamic>' is not a subtype of type 'int?'
⤷ type: _StackTrace
⤷ error: #0      PubMagicMetadata.fromMap (package:photos/models/metadata/file_magic.dart:91)

ce5354e19d/mobile/lib/models/metadata/file_magic.dart (L91)
This commit is contained in:
Manav Rathi
2024-09-23 15:44:23 +05:30
parent 72ba8bcd64
commit 630b6d4101
2 changed files with 36 additions and 7 deletions

View File

@@ -33,7 +33,7 @@ import {
import { EncryptedMagicMetadata } from "@/new/photos/types/magicMetadata";
import { detectFileTypeInfoFromChunk } from "@/new/photos/utils/detect-type";
import { readStream } from "@/new/photos/utils/native-stream";
import { ensure } from "@/utils/ensure";
import { ensure, ensureInteger, ensureNumber } from "@/utils/ensure";
import { CustomError, handleUploadError } from "@ente/shared/error";
import { addToCollection } from "services/collectionService";
import {
@@ -985,24 +985,33 @@ const extractImageOrVideoMetadata = async (
tryParseEpochMicrosecondsFromFileName(fileName) ?? modificationTime;
}
// To avoid introducing malformed data into the metadata fields (which the
// other clients might not expect and handle), we have extra "ensure" checks
// here that act as a safety valve if somehow the TypeScript type is lying.
//
// There is no deterministic sample we found that necessitated adding these
// extra checks, but we did get one user with a list in the width field of
// the metadata (it should've been an integer). The most probable theory is
// that somehow it made its way in through malformed Exif.
const metadata: Metadata = {
fileType,
title: fileName,
creationTime,
modificationTime,
creationTime: ensureInteger(creationTime),
modificationTime: ensureInteger(modificationTime),
hash,
};
const location = parsedMetadataJSON?.location ?? parsedMetadata?.location;
if (location) {
metadata.latitude = location.latitude;
metadata.longitude = location.longitude;
metadata.latitude = ensureNumber(location.latitude);
metadata.longitude = ensureNumber(location.longitude);
}
if (parsedMetadata) {
const { width: w, height: h } = parsedMetadata;
if (w) publicMagicMetadata.w = w;
if (h) publicMagicMetadata.h = h;
if (w) publicMagicMetadata.w = ensureInteger(w);
if (h) publicMagicMetadata.h = ensureInteger(h);
}
return { metadata, publicMagicMetadata };

View File

@@ -20,3 +20,23 @@ export const ensureString = (v: unknown): string => {
throw new Error(`Expected a string, instead found ${String(v)}`);
return v;
};
/**
* Throw an exception if the given value is not a number.
*/
export const ensureNumber = (v: unknown): number => {
if (typeof v != "number")
throw new Error(`Expected a number, instead found ${String(v)}`);
return v;
};
/**
* Throw an exception if the given value is not an integral number.
*/
export const ensureInteger = (v: unknown): number => {
if (typeof v != "number")
throw new Error(`Expected a number, instead found ${String(v)}`);
if (!Number.isInteger(v))
throw new Error(`Expected an integer, instead found ${v}`);
return v;
};