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:
@@ -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 };
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user