From 8480c929c107c4d700bbc2e9e427ca3d327e5daf Mon Sep 17 00:00:00 2001 From: Harald Kuhr Date: Thu, 8 Aug 2019 22:41:23 +0200 Subject: [PATCH] #477: Avoid cyclic loops in IFDs. --- .../imageio/metadata/tiff/TIFFReader.java | 43 +++++++++++------- .../imageio/metadata/tiff/TIFFReaderTest.java | 11 +++++ .../src/test/resources/exif/exif-loop.bin | Bin 0 -> 264 bytes 3 files changed, 38 insertions(+), 16 deletions(-) create mode 100644 imageio/imageio-metadata/src/test/resources/exif/exif-loop.bin diff --git a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/tiff/TIFFReader.java b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/tiff/TIFFReader.java index 687d774f..f27d94c2 100644 --- a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/tiff/TIFFReader.java +++ b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/tiff/TIFFReader.java @@ -81,6 +81,7 @@ public final class TIFFReader extends MetadataReader { private long length; private boolean longOffsets; private int offsetSize; + private Set parsedIFDs = new TreeSet<>(); @Override public Directory read(final ImageInputStream input) throws IOException { @@ -125,32 +126,34 @@ public final class TIFFReader extends MetadataReader { throw new IIOException(String.format("Wrong TIFF magic in input data: %04x, expected: %04x", magic, TIFF.TIFF_MAGIC)); } - length = getTIFFLength(input); + length = input.length(); return readLinkedIFDs(input); } - private long getTIFFLength(final ImageInputStream input) throws IOException { - // TODO: Scan to end, if length is unknown? - // Set to fixed size? 4 GB for TIFF, BigTIFF may be huge... - return input.length(); - } - private TIFFDirectory readLinkedIFDs(final ImageInputStream input) throws IOException { - long nextOffset = readOffset(input); + long ifdOffset = readOffset(input); List ifds = new ArrayList<>(); // Read linked IFDs - while (nextOffset != 0 && (length < 0 || length > nextOffset)) { + while (ifdOffset != 0) { try { - ifds.add(readIFD(input, nextOffset, VALID_TOP_LEVEL_IFDS)); + if ((length > 0 && ifdOffset >= length) || !parsedIFDs.add(ifdOffset)) { + // TODO: Issue warning + if (DEBUG) { + System.err.println("Bad IFD offset: " + ifdOffset); + } + break; + } - nextOffset = readOffset(input); + ifds.add(readIFD(input, ifdOffset, VALID_TOP_LEVEL_IFDS)); + + ifdOffset = readOffset(input); } catch (EOFException eof) { // catch EOF here as missing EOF marker - nextOffset = 0; + ifdOffset = 0; } } @@ -208,12 +211,20 @@ public final class TIFFReader extends MetadataReader { if (subIFDIds.contains(tagId)) { try { - long[] pointerOffsets = getPointerOffsets(entry); - List subIFDs = new ArrayList<>(pointerOffsets.length); + long[] ifdOffsets = getPointerOffsets(entry); + List subIFDs = new ArrayList<>(ifdOffsets.length); - for (long pointerOffset : pointerOffsets) { + for (long ifdOffset : ifdOffsets) { try { - subIFDs.add(readIFD(input, pointerOffset, VALID_SUB_IFDS.get(tagId))); + if ((length > 0 && ifdOffset >= length) || !parsedIFDs.add(ifdOffset)) { + // TODO: Issue warning + if (DEBUG) { + System.err.println("Bad IFD offset: " + ifdOffset); + } + break; + } + + subIFDs.add(readIFD(input, ifdOffset, VALID_SUB_IFDS.get(tagId))); } catch (EOFException eof) { // TODO: Issue warning diff --git a/imageio/imageio-metadata/src/test/java/com/twelvemonkeys/imageio/metadata/tiff/TIFFReaderTest.java b/imageio/imageio-metadata/src/test/java/com/twelvemonkeys/imageio/metadata/tiff/TIFFReaderTest.java index b0bb812e..a3f4132b 100644 --- a/imageio/imageio-metadata/src/test/java/com/twelvemonkeys/imageio/metadata/tiff/TIFFReaderTest.java +++ b/imageio/imageio-metadata/src/test/java/com/twelvemonkeys/imageio/metadata/tiff/TIFFReaderTest.java @@ -344,4 +344,15 @@ public class TIFFReaderTest extends MetadataReaderAbstractTest { assertEquals(3, directory.getDirectory(1).size()); } } + + @Test(timeout = 500) + public void testReadCyclicExifWithoutLoopOrOOME() throws IOException { + try (ImageInputStream stream = ImageIO.createImageInputStream(getResource("/exif/exif-loop.bin"))) { + CompoundDirectory directory = (CompoundDirectory) createReader().read(stream); + assertEquals(1, directory.directoryCount()); + assertEquals(12, directory.getDirectory(0).size()); + assertEquals("Polarr Photo Editor", directory.getDirectory(0).getEntryById(TIFF.TAG_SOFTWARE).getValue()); + assertEquals("2019:02:27 09:22:59", directory.getDirectory(0).getEntryById(TIFF.TAG_DATE_TIME).getValueAsString()); + } + } } diff --git a/imageio/imageio-metadata/src/test/resources/exif/exif-loop.bin b/imageio/imageio-metadata/src/test/resources/exif/exif-loop.bin new file mode 100644 index 0000000000000000000000000000000000000000..d467f21beabcdc15bcbd840962654872cc734531 GIT binary patch literal 264 zcmebEWzb?^VBlcjVPs%n0kVJ;KLaBpj4jr{$i%=56bH%8VPpfd85x*>3WcC-pbkb+ zC>yAfQ3|G)QHN0)iLHU8*AQd^gD?;;Wi$e_MS$#G?U^w343~g>4lrb32*}S#EGkk6 z$jC3rS8z?qEXgloU@$T;w6roXvNAGPFtD^TGO{wY1Zn{SmI(|D>>%2}$k=cJBf^yn Rm|&*!Gb~_+vBerdngF6&76kwR literal 0 HcmV?d00001