diff --git a/android/app/build.gradle b/android/app/build.gradle index c0cd0cfbf..003f3608d 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -190,8 +190,8 @@ dependencies { // - https://jitpack.io/p/deckerst/mp4parser // - https://jitpack.io/p/deckerst/pixymeta-android implementation 'com.github.deckerst:Android-TiffBitmapFactory:876e53870a' - implementation 'com.github.deckerst.mp4parser:isoparser:64b571fdfb' - implementation 'com.github.deckerst.mp4parser:muxer:64b571fdfb' + implementation 'com.github.deckerst.mp4parser:isoparser:6bfa6c23f7' + implementation 'com.github.deckerst.mp4parser:muxer:6bfa6c23f7' implementation 'com.github.deckerst:pixymeta-android:706bd73d6e' // huawei flavor only diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/DebugHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/DebugHandler.kt index 440e535e0..0ec5ace5c 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/DebugHandler.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/DebugHandler.kt @@ -15,11 +15,8 @@ import android.util.Log import androidx.exifinterface.media.ExifInterface import com.drew.metadata.file.FileTypeDirectory import deckers.thibault.aves.channel.calls.Coresult.Companion.safe -import deckers.thibault.aves.metadata.ExifInterfaceHelper -import deckers.thibault.aves.metadata.MediaMetadataRetrieverHelper -import deckers.thibault.aves.metadata.Metadata +import deckers.thibault.aves.metadata.* import deckers.thibault.aves.metadata.Mp4ParserHelper.dumpBoxes -import deckers.thibault.aves.metadata.PixyMetaHelper import deckers.thibault.aves.metadata.metadataextractor.Helper import deckers.thibault.aves.model.FieldMap import deckers.thibault.aves.utils.LogUtils @@ -345,7 +342,7 @@ class DebugHandler(private val context: Context) : MethodCallHandler { FileInputStream(it.fileDescriptor).use { stream -> stream.channel.use { channel -> val boxParser = PropertyBoxParserImpl().apply { - skippingBoxes( + val skippedTypes = listOf( // parsing `MediaDataBox` can take a long time MediaDataBox.TYPE, // parsing `SampleTableBox` or `FreeBox` may yield OOM @@ -354,6 +351,11 @@ class DebugHandler(private val context: Context) : MethodCallHandler { // then a large size from following "0000", which may yield OOM "0000", ) + setBoxSkipper { type, size -> + if (skippedTypes.contains(type)) return@setBoxSkipper true + if (size > Mp4ParserHelper.BOX_SIZE_DANGER_THRESHOLD) throw Exception("box (type=$type size=$size) is too large") + false + } } IsoFile(channel, boxParser).use { isoFile -> isoFile.dumpBoxes(sb) diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/Mp4ParserHelper.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/Mp4ParserHelper.kt index 358e82ad2..5f86a11a6 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/Mp4ParserHelper.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/Mp4ParserHelper.kt @@ -15,6 +15,9 @@ import java.io.FileInputStream import java.nio.channels.Channels object Mp4ParserHelper { + // arbitrary size to detect boxes that may yield an OOM + const val BOX_SIZE_DANGER_THRESHOLD = 3 * (1 shl 20) // MB + fun computeEdits(context: Context, uri: Uri, modifier: (isoFile: IsoFile) -> Unit): List> { // we can skip uninteresting boxes with a seekable data source val pfd = StorageUtils.openInputFileDescriptor(context, uri) ?: throw Exception("failed to open file descriptor for uri=$uri") @@ -23,13 +26,16 @@ object Mp4ParserHelper { stream.channel.use { channel -> val boxParser = PropertyBoxParserImpl().apply { // do not skip anything inside `MovieBox` as it will be parsed and rewritten for editing - skippingBoxes( + // do not skip weird boxes (like trailing "0000" box), to fail fast if it is large + val skippedTypes = listOf( // parsing `MediaDataBox` can take a long time MediaDataBox.TYPE, - // some files are padded with `0` but the parser does not stop, reads type "0000", - // then a large size from following "0000", which may yield OOM - "0000", ) + setBoxSkipper { type, size -> + if (skippedTypes.contains(type)) return@setBoxSkipper true + if (size > BOX_SIZE_DANGER_THRESHOLD) throw Exception("box (type=$type size=$size) is too large") + false + } } // creating `IsoFile` with a `File` or a `File.inputStream()` yields `No such device` IsoFile(channel, boxParser).use { isoFile -> diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/XMP.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/XMP.kt index 41e7f3e34..a1f0055a7 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/XMP.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/XMP.kt @@ -145,15 +145,17 @@ object XMP { FileInputStream(it.fileDescriptor).use { stream -> stream.channel.use { channel -> val boxParser = PropertyBoxParserImpl().apply { - skippingBoxes( + val skippedTypes = listOf( // parsing `MediaDataBox` can take a long time MediaDataBox.TYPE, // parsing `SampleTableBox` or `FreeBox` may yield OOM SampleTableBox.TYPE, FreeBox.TYPE, - // some files are padded with `0` but the parser does not stop, reads type "0000", - // then a large size from following "0000", which may yield OOM - "0000", ) + setBoxSkipper { type, size -> + if (skippedTypes.contains(type)) return@setBoxSkipper true + if (size > Mp4ParserHelper.BOX_SIZE_DANGER_THRESHOLD) throw Exception("box (type=$type size=$size) is too large") + false + } } // creating `IsoFile` with a `File` or a `File.inputStream()` yields `No such device` IsoFile(channel, boxParser).use { isoFile ->