From c4a09a693efa4cfa032dba732d471650fd496669 Mon Sep 17 00:00:00 2001 From: Vincent Privat Date: Sun, 19 Jun 2022 01:27:49 +0200 Subject: [PATCH] Make RandomAccessReader.isMotorolaByteOrder read only. If the byte order changes during extraction, a new reader is made via WithByteOrder. That new reader is naturally scoped to the sub-reading operation, and the byte order does not need to be reverted. --- Source/com/drew/imaging/tiff/TiffReader.java | 16 ++---- Source/com/drew/lang/ByteArrayReader.java | 23 ++++++-- .../com/drew/lang/RandomAccessFileReader.java | 23 ++++++-- Source/com/drew/lang/RandomAccessReader.java | 23 +++----- .../drew/lang/RandomAccessStreamReader.java | 37 +++++++++--- .../com/drew/metadata/avi/AviRiffHandler.java | 12 ++-- Source/com/drew/metadata/eps/EpsReader.java | 4 +- .../metadata/exif/ExifDescriptorBase.java | 4 +- .../drew/metadata/exif/ExifTiffHandler.java | 56 +++++++------------ .../PanasonicMakernoteDirectory.java | 8 +-- .../makernotes/SonyTag9050bDirectory.java | 4 +- .../com/drew/metadata/wav/WavRiffHandler.java | 7 ++- .../drew/metadata/webp/WebpRiffHandler.java | 14 ++--- Tests/com/drew/lang/RandomAccessTestBase.java | 13 ++--- 14 files changed, 134 insertions(+), 110 deletions(-) diff --git a/Source/com/drew/imaging/tiff/TiffReader.java b/Source/com/drew/imaging/tiff/TiffReader.java index 46f075683..3fb629adf 100644 --- a/Source/com/drew/imaging/tiff/TiffReader.java +++ b/Source/com/drew/imaging/tiff/TiffReader.java @@ -44,7 +44,7 @@ public class TiffReader * ignored or recovered from * @throws IOException an error occurred while accessing the required data */ - public void processTiff(@NotNull final RandomAccessReader reader, + public void processTiff(@NotNull RandomAccessReader reader, @NotNull final TiffHandler handler) throws TiffProcessingException, IOException { // Standard TIFF @@ -67,9 +67,9 @@ public void processTiff(@NotNull final RandomAccessReader reader, short byteOrderIdentifier = reader.getInt16(0); if (byteOrderIdentifier == 0x4d4d) { // "MM" - reader.setMotorolaByteOrder(true); + reader = reader.withByteOrder(true); } else if (byteOrderIdentifier == 0x4949) { // "II" - reader.setMotorolaByteOrder(false); + reader = reader.withByteOrder(false); } else { throw new TiffProcessingException("Unclear distinction between Motorola/Intel byte ordering: " + byteOrderIdentifier); } @@ -134,7 +134,7 @@ public void processTiff(@NotNull final RandomAccessReader reader, * @throws IOException an error occurred while accessing the required data */ public static void processIfd(@NotNull final TiffHandler handler, - @NotNull final RandomAccessReader reader, + @NotNull RandomAccessReader reader, @NotNull final Set processedIfdOffsets, final int ifdOffset, final boolean isBigTiff) throws IOException @@ -161,7 +161,6 @@ public static void processIfd(@NotNull final TiffHandler handler, // - 8 bytes: component count // - 8 bytes: inline value, or offset pointer if too large to fit in eight bytes - Boolean resetByteOrder = null; try { // Check for directories we've already visited to avoid stack overflows when recursive/cyclic directory structures exist. // Note that we track these offsets in the global frame, not the reader's local frame. @@ -169,7 +168,7 @@ public static void processIfd(@NotNull final TiffHandler handler, // remember that we've visited this directory so that we don't visit it again later if (!processedIfdOffsets.add(globalIfdOffset)) { - return; + return; } // Validate IFD offset @@ -188,9 +187,8 @@ public static void processIfd(@NotNull final TiffHandler handler, // Here we detect switched bytes that suggest this problem, and temporarily swap the byte order. // This was discussed in GitHub issue #136. if (!isBigTiff && dirTagCount > 0xFF && (dirTagCount & 0xFF) == 0) { - resetByteOrder = reader.isMotorolaByteOrder(); dirTagCount >>= 8; - reader.setMotorolaByteOrder(!reader.isMotorolaByteOrder()); + reader = reader.withByteOrder(!reader.isMotorolaByteOrder()); } int dirLength = isBigTiff @@ -312,8 +310,6 @@ public static void processIfd(@NotNull final TiffHandler handler, } } finally { handler.endingIFD(); - if (resetByteOrder != null) - reader.setMotorolaByteOrder(resetByteOrder); } } diff --git a/Source/com/drew/lang/ByteArrayReader.java b/Source/com/drew/lang/ByteArrayReader.java index 6a47d78c0..2e4f88667 100644 --- a/Source/com/drew/lang/ByteArrayReader.java +++ b/Source/com/drew/lang/ByteArrayReader.java @@ -51,6 +51,14 @@ public ByteArrayReader(@NotNull byte[] buffer) @com.drew.lang.annotations.SuppressWarnings(value = "EI_EXPOSE_REP2", justification = "Design intent") public ByteArrayReader(@NotNull byte[] buffer, int baseOffset) { + this(buffer, baseOffset, true); + } + + @SuppressWarnings({ "ConstantConditions" }) + @com.drew.lang.annotations.SuppressWarnings(value = "EI_EXPOSE_REP2", justification = "Design intent") + public ByteArrayReader(@NotNull byte[] buffer, int baseOffset, boolean isMotorolaByteOrder) + { + super(isMotorolaByteOrder); if (buffer == null) throw new NullPointerException(); if (baseOffset < 0) @@ -61,13 +69,20 @@ public ByteArrayReader(@NotNull byte[] buffer, int baseOffset) } @Override - public RandomAccessReader withShiftedBaseOffset(int shift) throws IOException { + public ByteArrayReader withByteOrder(boolean isMotorolaByteOrder) { + if (isMotorolaByteOrder == isMotorolaByteOrder()) { + return this; + } else { + return new ByteArrayReader(_buffer, _baseOffset, isMotorolaByteOrder); + } + } + + @Override + public ByteArrayReader withShiftedBaseOffset(int shift) throws IOException { if (shift == 0) { return this; } else { - RandomAccessReader reader = new ByteArrayReader(_buffer, _baseOffset + shift); - reader.setMotorolaByteOrder(isMotorolaByteOrder()); - return reader; + return new ByteArrayReader(_buffer, _baseOffset + shift, isMotorolaByteOrder()); } } diff --git a/Source/com/drew/lang/RandomAccessFileReader.java b/Source/com/drew/lang/RandomAccessFileReader.java index 513bb0e34..37b2fa6c2 100644 --- a/Source/com/drew/lang/RandomAccessFileReader.java +++ b/Source/com/drew/lang/RandomAccessFileReader.java @@ -52,6 +52,14 @@ public RandomAccessFileReader(@NotNull RandomAccessFile file) throws IOException @com.drew.lang.annotations.SuppressWarnings(value = "EI_EXPOSE_REP2", justification = "Design intent") public RandomAccessFileReader(@NotNull RandomAccessFile file, int baseOffset) throws IOException { + this(file, baseOffset, true); + } + + @SuppressWarnings({ "ConstantConditions" }) + @com.drew.lang.annotations.SuppressWarnings(value = "EI_EXPOSE_REP2", justification = "Design intent") + public RandomAccessFileReader(@NotNull RandomAccessFile file, int baseOffset, boolean isMotorolaByteOrder) throws IOException + { + super(isMotorolaByteOrder); if (file == null) throw new NullPointerException(); @@ -61,13 +69,20 @@ public RandomAccessFileReader(@NotNull RandomAccessFile file, int baseOffset) th } @Override - public RandomAccessReader withShiftedBaseOffset(int shift) throws IOException { + public RandomAccessFileReader withByteOrder(boolean isMotorolaByteOrder) throws IOException { + if (isMotorolaByteOrder == isMotorolaByteOrder()) { + return this; + } else { + return new RandomAccessFileReader(_file, _baseOffset, isMotorolaByteOrder); + } + } + + @Override + public RandomAccessFileReader withShiftedBaseOffset(int shift) throws IOException { if (shift == 0) { return this; } else { - RandomAccessReader reader = new RandomAccessFileReader(_file, _baseOffset + shift); - reader.setMotorolaByteOrder(isMotorolaByteOrder()); - return reader; + return new RandomAccessFileReader(_file, _baseOffset + shift, isMotorolaByteOrder()); } } diff --git a/Source/com/drew/lang/RandomAccessReader.java b/Source/com/drew/lang/RandomAccessReader.java index 8424d6917..338d363bb 100644 --- a/Source/com/drew/lang/RandomAccessReader.java +++ b/Source/com/drew/lang/RandomAccessReader.java @@ -45,7 +45,14 @@ */ public abstract class RandomAccessReader { - private boolean _isMotorolaByteOrder = true; + private final boolean _isMotorolaByteOrder; + + protected RandomAccessReader(boolean isMotorolaByteOrder) + { + _isMotorolaByteOrder = isMotorolaByteOrder; + } + + public abstract RandomAccessReader withByteOrder(boolean isMotorolaByteOrder) throws IOException; public abstract RandomAccessReader withShiftedBaseOffset(int shift) throws IOException; @@ -106,20 +113,6 @@ public abstract class RandomAccessReader */ public abstract long getLength() throws IOException; - /** - * Sets the endianness of this reader. - * - * - * @param motorolaByteOrder true for Motorola/big endian, false for Intel/little endian - */ - public void setMotorolaByteOrder(boolean motorolaByteOrder) - { - _isMotorolaByteOrder = motorolaByteOrder; - } - /** * Gets the endianness of this reader. *