From 672aa1a0483536a1dd22b70092072878ed555c93 Mon Sep 17 00:00:00 2001 From: Oliver Schmidtmer Date: Tue, 2 Feb 2016 23:52:03 +0100 Subject: [PATCH 1/2] Continue reading the metadata if invalid tags were found --- .../imageio/metadata/exif/EXIFReader.java | 60 ++++++++---------- .../imageio/metadata/exif/EXIFReaderTest.java | 8 +++ .../src/test/resources/exif/emptyexiftag.tif | Bin 0 -> 824 bytes 3 files changed, 35 insertions(+), 33 deletions(-) create mode 100644 imageio/imageio-metadata/src/test/resources/exif/emptyexiftag.tif diff --git a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/EXIFReader.java b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/EXIFReader.java index 284e45f0..792d3b9a 100644 --- a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/EXIFReader.java +++ b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/EXIFReader.java @@ -71,7 +71,7 @@ public final class EXIFReader extends MetadataReader { else if (bom[0] == 'M' && bom[1] == 'M') { input.setByteOrder(ByteOrder.BIG_ENDIAN); } - else { + else { throw new IIOException(String.format("Invalid TIFF byte order mark '%s', expected: 'II' or 'MM'", StringUtil.decode(bom, 0, bom.length, "ASCII"))); } @@ -79,7 +79,7 @@ public final class EXIFReader extends MetadataReader { // http://www.awaresystems.be/imaging/tiff/bigtiff.html int magic = input.readUnsignedShort(); if (magic != TIFF.TIFF_MAGIC) { - throw new IIOException(String.format("Wrong TIFF magic in EXIF data: %04x, expected: %04x", magic, TIFF.TIFF_MAGIC)); + throw new IIOException(String.format("Wrong TIFF magic in EXIF data: %04x, expected: %04x", magic, TIFF.TIFF_MAGIC)); } long directoryOffset = input.readUnsignedInt(); @@ -107,14 +107,9 @@ public final class EXIFReader extends MetadataReader { for (int i = 0; i < entryCount; i++) { EXIFEntry entry = readEntry(pInput); - if (entry == null) { -// System.err.println("Expected: " + entryCount + " values, found only " + i); - // TODO: Log warning? - nextOffset = 0; - break; + if (entry != null) { + entries.add(entry); } - - entries.add(entry); } if (readLinked) { @@ -138,7 +133,7 @@ public final class EXIFReader extends MetadataReader { ); ifds.add(0, new IFD(entries)); - + return new EXIFDirectory(ifds); } @@ -170,7 +165,7 @@ public final class EXIFReader extends MetadataReader { // Replace the entry with parsed data entries.set(i, new EXIFEntry(tagId, subIFDs.get(0), entry.getType())); } - else { + else { // Replace the entry with parsed data entries.set(i, new EXIFEntry(tagId, subIFDs.toArray(new IFD[subIFDs.size()]), entry.getType())); } @@ -207,7 +202,9 @@ public final class EXIFReader extends MetadataReader { offsets = (long[]) value; } else { - throw new IIOException(String.format("Unknown pointer type: %s", (value != null ? value.getClass() : null))); + throw new IIOException(String.format("Unknown pointer type: %s", (value != null + ? value.getClass() + : null))); } return offsets; @@ -218,11 +215,6 @@ public final class EXIFReader extends MetadataReader { int tagId = pInput.readUnsignedShort(); short type = pInput.readShort(); - // This isn't really an entry, and the directory entry count was wrong OR bad data... - if (tagId == 0 && type == 0) { - return null; - } - int count = pInput.readInt(); // Number of values // It's probably a spec violation to have count 0, but we'll be lenient about it @@ -231,32 +223,33 @@ public final class EXIFReader extends MetadataReader { } if (type <= 0 || type > 13) { + pInput.skipBytes(4); // read Value + // Invalid tag, this is just for debugging - long offset = pInput.getStreamPosition() - 8l; + long offset = pInput.getStreamPosition() - 12l; if (DEBUG) { System.err.printf("Bad EXIF data @%08x\n", pInput.getStreamPosition()); System.err.println("tagId: " + tagId + (tagId <= 0 ? " (INVALID)" : "")); System.err.println("type: " + type + " (INVALID)"); System.err.println("count: " + count); - } - pInput.mark(); - pInput.seek(offset); + pInput.mark(); + pInput.seek(offset); - try { - byte[] bytes = new byte[8 + Math.min(120, Math.max(24, count))]; - int len = pInput.read(bytes); + try { + byte[] bytes = new byte[8 + Math.min(120, Math.max(24, count))]; + int len = pInput.read(bytes); - if (DEBUG) { - System.err.print(HexDump.dump(offset, bytes, 0, len)); - System.err.println(len < count ? "[...]" : ""); + if (DEBUG) { + System.err.print(HexDump.dump(offset, bytes, 0, len)); + System.err.println(len < count ? "[...]" : ""); + } + } + finally { + pInput.reset(); } } - finally { - pInput.reset(); - } - return null; } @@ -504,7 +497,8 @@ public final class EXIFReader extends MetadataReader { ////////////////////// // TODO: Stream based hex dump util? public static class HexDump { - private HexDump() {} + private HexDump() { + } private static final int WIDTH = 32; @@ -518,7 +512,7 @@ public final class EXIFReader extends MetadataReader { int i; for (i = 0; i < len; i++) { if (i % WIDTH == 0) { - if (i > 0 ) { + if (i > 0) { builder.append("\n"); } builder.append(String.format("%08x: ", i + off + offset)); diff --git a/imageio/imageio-metadata/src/test/java/com/twelvemonkeys/imageio/metadata/exif/EXIFReaderTest.java b/imageio/imageio-metadata/src/test/java/com/twelvemonkeys/imageio/metadata/exif/EXIFReaderTest.java index 1249de6c..8867871e 100644 --- a/imageio/imageio-metadata/src/test/java/com/twelvemonkeys/imageio/metadata/exif/EXIFReaderTest.java +++ b/imageio/imageio-metadata/src/test/java/com/twelvemonkeys/imageio/metadata/exif/EXIFReaderTest.java @@ -276,4 +276,12 @@ public class EXIFReaderTest extends MetadataReaderAbstractTest { assertNotNull(interop); assertEquals(0, interop.size()); } + + @Test + public void testReadExifWithEmptyTag() throws IOException { + ImageInputStream stream = ImageIO.createImageInputStream(getResource("/exif/emptyexiftag.tif")); + CompoundDirectory directory = (CompoundDirectory) createReader().read(stream); + assertEquals(3, directory.directoryCount()); + stream.close(); + } } diff --git a/imageio/imageio-metadata/src/test/resources/exif/emptyexiftag.tif b/imageio/imageio-metadata/src/test/resources/exif/emptyexiftag.tif new file mode 100644 index 0000000000000000000000000000000000000000..40fa550734e371f597d84804722211f9a254eecc GIT binary patch literal 824 zcmebEWzb?^V2EIl@MAET!;omfug9cD4mqA9IK^#N~9RPC&VW2R|F$y7hl5n7K;|LT+?193liwG1(TVOcVv50?d s-~h!rQyl}P0m4sGDgnhV!BoOzOk#krqXY=nl)+?&2m~fSVCrB102IkSRsaA1 literal 0 HcmV?d00001 From 6796910091ee6c12afd0d551910e0837a35f0861 Mon Sep 17 00:00:00 2001 From: Oliver Schmidtmer Date: Tue, 16 Feb 2016 22:52:57 +0100 Subject: [PATCH 2/2] Fix reading bad SubIFDs again --- .../imageio/metadata/exif/EXIFReader.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/EXIFReader.java b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/EXIFReader.java index 792d3b9a..2c872b45 100644 --- a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/EXIFReader.java +++ b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/EXIFReader.java @@ -105,16 +105,27 @@ public final class EXIFReader extends MetadataReader { } for (int i = 0; i < entryCount; i++) { - EXIFEntry entry = readEntry(pInput); + try { + EXIFEntry entry = readEntry(pInput); - if (entry != null) { - entries.add(entry); + if (entry != null) { + entries.add(entry); + } + } + catch (IIOException e) { + break; } } if (readLinked) { if (nextOffset == -1) { - nextOffset = pInput.readUnsignedInt(); + try { + nextOffset = pInput.readUnsignedInt(); + } + catch (EOFException e) { + // catch EOF here as missing EOF marker + nextOffset = 0; + } } // Read linked IFDs