drewnoakes / metadata-extractor

Extracts Exif, IPTC, XMP, ICC and other metadata from image, video and audio files
Apache License 2.0
2.59k stars 480 forks source link

Various unchecked exceptions while parsing malformed inputs #422

Open alpire opened 5 years ago

alpire commented 5 years ago

ImageMetadataReader.readMetadata can lead to various unchecked exceptions when parsing malformed psd, mp3, heif, and jpeg files.

Steps to repro

  1. Download the malformed inputs and extract them.
  2. For each input, run java -ea -cp metadata-extractor-2.12.0.jar com.drew.imaging.ImageMetadataReader <input> to reproduce the exceptions.

Stacktraces

$ java -ea -cp metadata-extractor-2.12.0.jar com.drew.imaging.ImageMetadataReader ./psd/AssertionError.PsdReader.extract
Exception in thread "main" java.lang.AssertionError
        at com.drew.metadata.photoshop.PsdReader.extract(PsdReader.java:110)
        at com.drew.imaging.psd.PsdMetadataReader.readMetadata(PsdMetadataReader.java:57)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:156)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:125)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:205)
        at com.drew.imaging.ImageMetadataReader.main(ImageMetadataReader.java:254)
$ java -cp metadata-extractor-2.12.0.jar com.drew.imaging.ImageMetadataReader ./mp3/ArithmeticException.Mp3Reader.extract
java.lang.ArithmeticException: / by zero
        at com.drew.metadata.mp3.Mp3Reader.extract(Mp3Reader.java:156)
        at com.drew.imaging.mp3.Mp3MetadataReader.readMetadata(Mp3MetadataReader.java:58)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:180)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:125)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:205)
        at com.drew.imaging.ImageMetadataReader.main(ImageMetadataReader.java:254)
$ java -cp metadata-extractor-2.12.0.jar com.drew.imaging.ImageMetadataReader ./mp3/ArrayIndexOutOfBoundsException.Mp3Reader.setBitrate
java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 14
        at com.drew.metadata.mp3.Mp3Reader.setBitrate(Mp3Reader.java:216)
        at com.drew.metadata.mp3.Mp3Reader.extract(Mp3Reader.java:156)
        at com.drew.imaging.mp3.Mp3MetadataReader.readMetadata(Mp3MetadataReader.java:58)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:180)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:125)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:205)
        at com.drew.imaging.ImageMetadataReader.main(ImageMetadataReader.java:254)
$ java -cp metadata-extractor-2.12.0.jar com.drew.imaging.ImageMetadataReader ./mp3/ArrayIndexOutOfBoundsException.Mp3Reader.extract
java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
        at com.drew.metadata.mp3.Mp3Reader.extract(Mp3Reader.java:105)
        at com.drew.imaging.mp3.Mp3MetadataReader.readMetadata(Mp3MetadataReader.java:58)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:180)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:125)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:205)
        at com.drew.imaging.ImageMetadataReader.main(ImageMetadataReader.java:254)
$ java -cp metadata-extractor-2.12.0.jar com.drew.imaging.ImageMetadataReader ./jpeg/NegativeArraySizeException.DuckyReader.extract
java.lang.NegativeArraySizeException: -4
        at com.drew.lang.SequentialByteArrayReader.getBytes(SequentialByteArrayReader.java:77)
        at com.drew.lang.SequentialReader.getStringValue(SequentialReader.java:328)
        at com.drew.metadata.photoshop.DuckyReader.extract(DuckyReader.java:99)
        at com.drew.metadata.photoshop.DuckyReader.readJpegSegments(DuckyReader.java:60)
        at com.drew.imaging.jpeg.JpegMetadataReader.processJpegSegmentData(JpegMetadataReader.java:134)
        at com.drew.imaging.jpeg.JpegMetadataReader.process(JpegMetadataReader.java:126)
        at com.drew.imaging.jpeg.JpegMetadataReader.readMetadata(JpegMetadataReader.java:77)
        at com.drew.imaging.jpeg.JpegMetadataReader.readMetadata(JpegMetadataReader.java:84)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:147)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:125)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:205)
        at com.drew.imaging.ImageMetadataReader.main(ImageMetadataReader.java:254)
$ java -cp metadata-extractor-2.12.0.jar com.drew.imaging.ImageMetadataReader ./heif/NullPointerException.HeifPictureHandler.processBox
java.lang.NullPointerException
        at com.drew.metadata.heif.boxes.ItemLocationBox.<init>(ItemLocationBox.java:86)
        at com.drew.metadata.heif.HeifPictureHandler.processBox(HeifPictureHandler.java:88)
        at com.drew.imaging.heif.HeifReader.processBoxes(HeifReader.java:55)
        at com.drew.imaging.heif.HeifReader.processBoxes(HeifReader.java:53)
        at com.drew.imaging.heif.HeifReader.extract(HeifReader.java:38)
        at com.drew.imaging.heif.HeifMetadataReader.readMetadata(HeifMetadataReader.java:40)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:184)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:125)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:205)
        at com.drew.imaging.ImageMetadataReader.main(ImageMetadataReader.java:254)
$ java -cp metadata-extractor-2.12.0.jar com.drew.imaging.ImageMetadataReader ./heif/NegativeArraySizeException.HeifReader.processBoxes
java.lang.NegativeArraySizeException: -2
        at com.drew.lang.StreamReader.getBytes(StreamReader.java:71)
        at com.drew.imaging.heif.HeifReader.processBoxes(HeifReader.java:55)
        at com.drew.imaging.heif.HeifReader.processBoxes(HeifReader.java:53)
        at com.drew.imaging.heif.HeifReader.extract(HeifReader.java:38)
        at com.drew.imaging.heif.HeifMetadataReader.readMetadata(HeifMetadataReader.java:40)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:184)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:125)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:205)
        at com.drew.imaging.ImageMetadataReader.main(ImageMetadataReader.java:254)
$ java -cp metadata-extractor-2.12.0.jar com.drew.imaging.ImageMetadataReader ./heif/NegativeArraySizeException.ItemInfoBox.init
java.lang.NegativeArraySizeException: -2147483625
        at com.drew.lang.SequentialByteArrayReader.getBytes(SequentialByteArrayReader.java:77)
        at com.drew.metadata.heif.boxes.ItemInfoBox.<init>(ItemInfoBox.java:53)
        at com.drew.metadata.heif.HeifPictureHandler.processBox(HeifPictureHandler.java:85)
        at com.drew.imaging.heif.HeifReader.processBoxes(HeifReader.java:55)
        at com.drew.imaging.heif.HeifReader.processBoxes(HeifReader.java:53)
        at com.drew.imaging.heif.HeifReader.extract(HeifReader.java:38)
        at com.drew.imaging.heif.HeifMetadataReader.readMetadata(HeifMetadataReader.java:40)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:184)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:125)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:205)
        at com.drew.imaging.ImageMetadataReader.main(ImageMetadataReader.java:254)
$ java -cp metadata-extractor-2.12.0.jar com.drew.imaging.ImageMetadataReader ./heif/IllegalArgumentException.HeifReader.processBoxes
java.lang.IllegalArgumentException: n must be zero or greater.
        at com.drew.lang.StreamReader.skip(StreamReader.java:95)
        at com.drew.imaging.heif.HeifReader.processBoxes(HeifReader.java:57)
        at com.drew.imaging.heif.HeifReader.processBoxes(HeifReader.java:53)
        at com.drew.imaging.heif.HeifReader.extract(HeifReader.java:38)
        at com.drew.imaging.heif.HeifMetadataReader.readMetadata(HeifMetadataReader.java:40)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:184)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:125)
        at com.drew.imaging.ImageMetadataReader.readMetadata(ImageMetadataReader.java:205)
        at com.drew.imaging.ImageMetadataReader.main(ImageMetadataReader.java:254)

The files were generated by fuzzing and are (probably) not valid file formats.

drewnoakes commented 5 years ago

Thank you very much for these! It's a goal of the library to always handle malformed inputs as gracefully as possible and never throw back to the public API caller.

@alpire are you willing for us to add these to the (public) image library for regression testing?

I've created an issue to also test these against the .NET implementation.

Thanks again!

alpire commented 5 years ago

@drewnoakes: Glad you're finding those helpful. Feel free to add those to the image library, and generally use them as you see fit :)

drewnoakes commented 4 years ago