Loading media/java/android/media/ExifInterface.java +94 −43 Original line number Diff line number Diff line Loading @@ -1197,8 +1197,9 @@ public class ExifInterface { } bytesRead += 2; int length = dataInputStream.readUnsignedShort() - 2; if (length < 0) if (length < 0) { throw new IOException("Invalid length"); } bytesRead += length; switch (marker) { case MARKER_APP1: { Loading @@ -1221,6 +1222,9 @@ public class ExifInterface { if (length <= 0) { throw new IOException("Invalid exif"); } if (DEBUG) { Log.d(TAG, "readExifSegment with a byte array (length: " + length + ")"); } byte[] bytes = new byte[length]; if (dataInputStream.read(bytes) != length) { throw new IOException("Invalid exif"); Loading Loading @@ -1309,8 +1313,9 @@ public class ExifInterface { case MARKER_APP1: { // Rewrite EXIF segment int length = dataInputStream.readUnsignedShort() - 2; if (length < 0) if (length < 0) { throw new IOException("Invalid length"); } bytesRead += 2; int read; while ((read = dataInputStream.read( Loading @@ -1331,8 +1336,9 @@ public class ExifInterface { // Copy JPEG segment int length = dataInputStream.readUnsignedShort(); dataOutputStream.writeUnsignedShort(length); if (length < 0) if (length < 0) { throw new IOException("Invalid length"); } length -= 2; bytesRead += 2; int read; Loading Loading @@ -1385,9 +1391,10 @@ public class ExifInterface { } firstIfdOffset -= 8; if (firstIfdOffset > 0) { if (dataInputStream.skip(firstIfdOffset) != firstIfdOffset) if (dataInputStream.skip(firstIfdOffset) != firstIfdOffset) { throw new IOException("Couldn't jump to first Ifd: " + firstIfdOffset); } } // Read primary image TIFF image file directory. readImageFileDirectory(dataInputStream, IFD_TIFF_HINT); Loading Loading @@ -1582,8 +1589,16 @@ public class ExifInterface { // Reads image file directory, which is a tag group in EXIF. private void readImageFileDirectory(ByteOrderAwarenessDataInputStream dataInputStream, int hint) throws IOException { if (dataInputStream.peek() + 2 > dataInputStream.mLength) { // Return if there is no data from the offset. return; } // See JEITA CP-3451 Figure 5. page 9. short numberOfDirectoryEntry = dataInputStream.readShort(); if (dataInputStream.peek() + 12 * numberOfDirectoryEntry > dataInputStream.mLength) { // Return if the size of entries is too big. return; } if (DEBUG) { Log.d(TAG, "numberOfDirectoryEntry: " + numberOfDirectoryEntry); Loading @@ -1595,10 +1610,25 @@ public class ExifInterface { int numberOfComponents = dataInputStream.readInt(); long nextEntryOffset = dataInputStream.peek() + 4; // next four bytes is for data // offset or value. // Look up a corresponding tag from tag number String tagName = (String) sExifTagMapsForReading[hint].get(tagNumber); if (DEBUG) { Log.d(TAG, String.format("tagNumber: %d, dataFormat: %d, numberOfComponents: %d", tagNumber, dataFormat, numberOfComponents)); Log.d(TAG, String.format("hint: %d, tagNumber: %d, tagName: %s, dataFormat: %d," + "numberOfComponents: %d", hint, tagNumber, tagName, dataFormat, numberOfComponents)); } if (tagName == null || dataFormat <= 0 || dataFormat >= IFD_FORMAT_BYTES_PER_FORMAT.length) { // Skip if the parsed tag number is not defined or invalid data format. if (tagName == null) { Log.w(TAG, "Skip the tag entry since tag number is not defined: " + tagNumber); } else { Log.w(TAG, "Skip the tag entry since data format is invalid: " + dataFormat); } dataInputStream.seek(nextEntryOffset); continue; } // Read a value from data field or seek to the value offset which is stored in data Loading @@ -1609,19 +1639,21 @@ public class ExifInterface { if (DEBUG) { Log.d(TAG, "seek to data offset: " + offset); } if (offset + byteCount <= dataInputStream.mLength) { dataInputStream.seek(offset); } // Look up a corresponding tag from tag number String tagName = (String) sExifTagMapsForReading[hint].get(tagNumber); // Skip if the parsed tag number is not defined. if (tagName == null) { } else { // Skip if invalid data offset. Log.w(TAG, "Skip the tag entry since data offset is invalid: " + offset); dataInputStream.seek(nextEntryOffset); continue; } } // Recursively parse IFD when a IFD pointer tag appears. int innerIfdHint = getIfdHintFromTagNumber(tagNumber); if (DEBUG) { Log.d(TAG, "innerIfdHint: " + innerIfdHint + " byteCount: " + byteCount); } if (innerIfdHint >= 0) { long offset = -1L; // Get offset from data field Loading Loading @@ -1650,9 +1682,11 @@ public class ExifInterface { if (DEBUG) { Log.d(TAG, String.format("Offset: %d, tagName: %s", offset, tagName)); } if (offset > 0L) { if (offset > 0L && offset < dataInputStream.mLength) { dataInputStream.seek(offset); readImageFileDirectory(dataInputStream, innerIfdHint); } else { Log.w(TAG, "Skip jump into the IFD since its offset is invalid: " + offset); } dataInputStream.seek(nextEntryOffset); Loading Loading @@ -1683,16 +1717,19 @@ public class ExifInterface { } } if (dataInputStream.peek() + 4 <= dataInputStream.mLength) { long nextIfdOffset = dataInputStream.readUnsignedInt(); if (DEBUG) { Log.d(TAG, String.format("nextIfdOffset: %d", nextIfdOffset)); } // The next IFD offset needs to be bigger than 8 since the first IFD offset is at least 8. if (nextIfdOffset > 8) { // The next IFD offset needs to be bigger than 8 // since the first IFD offset is at least 8. if (nextIfdOffset > 8 && nextIfdOffset < dataInputStream.mLength) { dataInputStream.seek(nextIfdOffset); readImageFileDirectory(dataInputStream, IFD_THUMBNAIL_HINT); } } } // Reads a value from where the entry value are stored. private String readExifEntryValue(ByteOrderAwarenessDataInputStream dataInputStream, Loading Loading @@ -1748,17 +1785,18 @@ public class ExifInterface { } StringBuilder stringBuilder = new StringBuilder(); while (true) { while (index < numberOfComponents) { int ch = bytes[index]; if (ch == 0) if (ch == 0) { break; if (ch >= 32) } if (ch >= 32) { stringBuilder.append((char) ch); else } else { stringBuilder.append('?'); } ++index; if (index == numberOfComponents) break; } return stringBuilder.toString(); } Loading @@ -1772,9 +1810,10 @@ public class ExifInterface { // Gets the corresponding IFD group index of the given tag number for writing Exif Tags. private static int getIfdHintFromTagNumber(int tagNumber) { for (int i = 0; i < IFD_POINTER_TAG_HINTS.length; ++i) { if (IFD_POINTER_TAGS[i].number == tagNumber) if (IFD_POINTER_TAGS[i].number == tagNumber) { return IFD_POINTER_TAG_HINTS[i]; } } return -1; } Loading Loading @@ -2076,9 +2115,10 @@ public class ExifInterface { public void seek(long byteCount) throws IOException { mPosition = 0L; reset(); if (skip(byteCount) != byteCount) if (skip(byteCount) != byteCount) { throw new IOException("Couldn't seek up to the byteCount"); } } public long peek() { return mPosition; Loading @@ -2086,8 +2126,9 @@ public class ExifInterface { public void readFully(byte[] buffer) throws IOException { mPosition += buffer.length; if (mPosition > mLength) if (mPosition > mLength) { throw new EOFException(); } if (super.read(buffer, 0, buffer.length) != buffer.length) { throw new IOException("Couldn't read up to the length of buffer"); } Loading @@ -2095,22 +2136,26 @@ public class ExifInterface { public byte readByte() throws IOException { ++mPosition; if (mPosition > mLength) if (mPosition > mLength) { throw new EOFException(); } int ch = super.read(); if (ch < 0) if (ch < 0) { throw new EOFException(); } return (byte) ch; } public short readShort() throws IOException { mPosition += 2; if (mPosition > mLength) if (mPosition > mLength) { throw new EOFException(); } int ch1 = super.read(); int ch2 = super.read(); if ((ch1 | ch2) < 0) if ((ch1 | ch2) < 0) { throw new EOFException(); } if (mByteOrder == LITTLE_ENDIAN) { return (short) ((ch2 << 8) + (ch1)); } else if (mByteOrder == BIG_ENDIAN) { Loading @@ -2121,14 +2166,16 @@ public class ExifInterface { public int readInt() throws IOException { mPosition += 4; if (mPosition > mLength) if (mPosition > mLength) { throw new EOFException(); } int ch1 = super.read(); int ch2 = super.read(); int ch3 = super.read(); int ch4 = super.read(); if ((ch1 | ch2 | ch3 | ch4) < 0) if ((ch1 | ch2 | ch3 | ch4) < 0) { throw new EOFException(); } if (mByteOrder == LITTLE_ENDIAN) { return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + ch1); } else if (mByteOrder == BIG_ENDIAN) { Loading @@ -2146,12 +2193,14 @@ public class ExifInterface { public int readUnsignedShort() throws IOException { mPosition += 2; if (mPosition > mLength) if (mPosition > mLength) { throw new EOFException(); } int ch1 = super.read(); int ch2 = super.read(); if ((ch1 | ch2) < 0) if ((ch1 | ch2) < 0) { throw new EOFException(); } if (mByteOrder == LITTLE_ENDIAN) { return ((ch2 << 8) + (ch1)); } else if (mByteOrder == BIG_ENDIAN) { Loading @@ -2166,8 +2215,9 @@ public class ExifInterface { public long readLong() throws IOException { mPosition += 8; if (mPosition > mLength) if (mPosition > mLength) { throw new EOFException(); } int ch1 = super.read(); int ch2 = super.read(); int ch3 = super.read(); Loading @@ -2176,8 +2226,9 @@ public class ExifInterface { int ch6 = super.read(); int ch7 = super.read(); int ch8 = super.read(); if ((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0) if ((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0) { throw new EOFException(); } if (mByteOrder == LITTLE_ENDIAN) { return (((long) ch8 << 56) + ((long) ch7 << 48) + ((long) ch6 << 40) + ((long) ch5 << 32) + ((long) ch4 << 24) + ((long) ch3 << 16) Loading Loading
media/java/android/media/ExifInterface.java +94 −43 Original line number Diff line number Diff line Loading @@ -1197,8 +1197,9 @@ public class ExifInterface { } bytesRead += 2; int length = dataInputStream.readUnsignedShort() - 2; if (length < 0) if (length < 0) { throw new IOException("Invalid length"); } bytesRead += length; switch (marker) { case MARKER_APP1: { Loading @@ -1221,6 +1222,9 @@ public class ExifInterface { if (length <= 0) { throw new IOException("Invalid exif"); } if (DEBUG) { Log.d(TAG, "readExifSegment with a byte array (length: " + length + ")"); } byte[] bytes = new byte[length]; if (dataInputStream.read(bytes) != length) { throw new IOException("Invalid exif"); Loading Loading @@ -1309,8 +1313,9 @@ public class ExifInterface { case MARKER_APP1: { // Rewrite EXIF segment int length = dataInputStream.readUnsignedShort() - 2; if (length < 0) if (length < 0) { throw new IOException("Invalid length"); } bytesRead += 2; int read; while ((read = dataInputStream.read( Loading @@ -1331,8 +1336,9 @@ public class ExifInterface { // Copy JPEG segment int length = dataInputStream.readUnsignedShort(); dataOutputStream.writeUnsignedShort(length); if (length < 0) if (length < 0) { throw new IOException("Invalid length"); } length -= 2; bytesRead += 2; int read; Loading Loading @@ -1385,9 +1391,10 @@ public class ExifInterface { } firstIfdOffset -= 8; if (firstIfdOffset > 0) { if (dataInputStream.skip(firstIfdOffset) != firstIfdOffset) if (dataInputStream.skip(firstIfdOffset) != firstIfdOffset) { throw new IOException("Couldn't jump to first Ifd: " + firstIfdOffset); } } // Read primary image TIFF image file directory. readImageFileDirectory(dataInputStream, IFD_TIFF_HINT); Loading Loading @@ -1582,8 +1589,16 @@ public class ExifInterface { // Reads image file directory, which is a tag group in EXIF. private void readImageFileDirectory(ByteOrderAwarenessDataInputStream dataInputStream, int hint) throws IOException { if (dataInputStream.peek() + 2 > dataInputStream.mLength) { // Return if there is no data from the offset. return; } // See JEITA CP-3451 Figure 5. page 9. short numberOfDirectoryEntry = dataInputStream.readShort(); if (dataInputStream.peek() + 12 * numberOfDirectoryEntry > dataInputStream.mLength) { // Return if the size of entries is too big. return; } if (DEBUG) { Log.d(TAG, "numberOfDirectoryEntry: " + numberOfDirectoryEntry); Loading @@ -1595,10 +1610,25 @@ public class ExifInterface { int numberOfComponents = dataInputStream.readInt(); long nextEntryOffset = dataInputStream.peek() + 4; // next four bytes is for data // offset or value. // Look up a corresponding tag from tag number String tagName = (String) sExifTagMapsForReading[hint].get(tagNumber); if (DEBUG) { Log.d(TAG, String.format("tagNumber: %d, dataFormat: %d, numberOfComponents: %d", tagNumber, dataFormat, numberOfComponents)); Log.d(TAG, String.format("hint: %d, tagNumber: %d, tagName: %s, dataFormat: %d," + "numberOfComponents: %d", hint, tagNumber, tagName, dataFormat, numberOfComponents)); } if (tagName == null || dataFormat <= 0 || dataFormat >= IFD_FORMAT_BYTES_PER_FORMAT.length) { // Skip if the parsed tag number is not defined or invalid data format. if (tagName == null) { Log.w(TAG, "Skip the tag entry since tag number is not defined: " + tagNumber); } else { Log.w(TAG, "Skip the tag entry since data format is invalid: " + dataFormat); } dataInputStream.seek(nextEntryOffset); continue; } // Read a value from data field or seek to the value offset which is stored in data Loading @@ -1609,19 +1639,21 @@ public class ExifInterface { if (DEBUG) { Log.d(TAG, "seek to data offset: " + offset); } if (offset + byteCount <= dataInputStream.mLength) { dataInputStream.seek(offset); } // Look up a corresponding tag from tag number String tagName = (String) sExifTagMapsForReading[hint].get(tagNumber); // Skip if the parsed tag number is not defined. if (tagName == null) { } else { // Skip if invalid data offset. Log.w(TAG, "Skip the tag entry since data offset is invalid: " + offset); dataInputStream.seek(nextEntryOffset); continue; } } // Recursively parse IFD when a IFD pointer tag appears. int innerIfdHint = getIfdHintFromTagNumber(tagNumber); if (DEBUG) { Log.d(TAG, "innerIfdHint: " + innerIfdHint + " byteCount: " + byteCount); } if (innerIfdHint >= 0) { long offset = -1L; // Get offset from data field Loading Loading @@ -1650,9 +1682,11 @@ public class ExifInterface { if (DEBUG) { Log.d(TAG, String.format("Offset: %d, tagName: %s", offset, tagName)); } if (offset > 0L) { if (offset > 0L && offset < dataInputStream.mLength) { dataInputStream.seek(offset); readImageFileDirectory(dataInputStream, innerIfdHint); } else { Log.w(TAG, "Skip jump into the IFD since its offset is invalid: " + offset); } dataInputStream.seek(nextEntryOffset); Loading Loading @@ -1683,16 +1717,19 @@ public class ExifInterface { } } if (dataInputStream.peek() + 4 <= dataInputStream.mLength) { long nextIfdOffset = dataInputStream.readUnsignedInt(); if (DEBUG) { Log.d(TAG, String.format("nextIfdOffset: %d", nextIfdOffset)); } // The next IFD offset needs to be bigger than 8 since the first IFD offset is at least 8. if (nextIfdOffset > 8) { // The next IFD offset needs to be bigger than 8 // since the first IFD offset is at least 8. if (nextIfdOffset > 8 && nextIfdOffset < dataInputStream.mLength) { dataInputStream.seek(nextIfdOffset); readImageFileDirectory(dataInputStream, IFD_THUMBNAIL_HINT); } } } // Reads a value from where the entry value are stored. private String readExifEntryValue(ByteOrderAwarenessDataInputStream dataInputStream, Loading Loading @@ -1748,17 +1785,18 @@ public class ExifInterface { } StringBuilder stringBuilder = new StringBuilder(); while (true) { while (index < numberOfComponents) { int ch = bytes[index]; if (ch == 0) if (ch == 0) { break; if (ch >= 32) } if (ch >= 32) { stringBuilder.append((char) ch); else } else { stringBuilder.append('?'); } ++index; if (index == numberOfComponents) break; } return stringBuilder.toString(); } Loading @@ -1772,9 +1810,10 @@ public class ExifInterface { // Gets the corresponding IFD group index of the given tag number for writing Exif Tags. private static int getIfdHintFromTagNumber(int tagNumber) { for (int i = 0; i < IFD_POINTER_TAG_HINTS.length; ++i) { if (IFD_POINTER_TAGS[i].number == tagNumber) if (IFD_POINTER_TAGS[i].number == tagNumber) { return IFD_POINTER_TAG_HINTS[i]; } } return -1; } Loading Loading @@ -2076,9 +2115,10 @@ public class ExifInterface { public void seek(long byteCount) throws IOException { mPosition = 0L; reset(); if (skip(byteCount) != byteCount) if (skip(byteCount) != byteCount) { throw new IOException("Couldn't seek up to the byteCount"); } } public long peek() { return mPosition; Loading @@ -2086,8 +2126,9 @@ public class ExifInterface { public void readFully(byte[] buffer) throws IOException { mPosition += buffer.length; if (mPosition > mLength) if (mPosition > mLength) { throw new EOFException(); } if (super.read(buffer, 0, buffer.length) != buffer.length) { throw new IOException("Couldn't read up to the length of buffer"); } Loading @@ -2095,22 +2136,26 @@ public class ExifInterface { public byte readByte() throws IOException { ++mPosition; if (mPosition > mLength) if (mPosition > mLength) { throw new EOFException(); } int ch = super.read(); if (ch < 0) if (ch < 0) { throw new EOFException(); } return (byte) ch; } public short readShort() throws IOException { mPosition += 2; if (mPosition > mLength) if (mPosition > mLength) { throw new EOFException(); } int ch1 = super.read(); int ch2 = super.read(); if ((ch1 | ch2) < 0) if ((ch1 | ch2) < 0) { throw new EOFException(); } if (mByteOrder == LITTLE_ENDIAN) { return (short) ((ch2 << 8) + (ch1)); } else if (mByteOrder == BIG_ENDIAN) { Loading @@ -2121,14 +2166,16 @@ public class ExifInterface { public int readInt() throws IOException { mPosition += 4; if (mPosition > mLength) if (mPosition > mLength) { throw new EOFException(); } int ch1 = super.read(); int ch2 = super.read(); int ch3 = super.read(); int ch4 = super.read(); if ((ch1 | ch2 | ch3 | ch4) < 0) if ((ch1 | ch2 | ch3 | ch4) < 0) { throw new EOFException(); } if (mByteOrder == LITTLE_ENDIAN) { return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + ch1); } else if (mByteOrder == BIG_ENDIAN) { Loading @@ -2146,12 +2193,14 @@ public class ExifInterface { public int readUnsignedShort() throws IOException { mPosition += 2; if (mPosition > mLength) if (mPosition > mLength) { throw new EOFException(); } int ch1 = super.read(); int ch2 = super.read(); if ((ch1 | ch2) < 0) if ((ch1 | ch2) < 0) { throw new EOFException(); } if (mByteOrder == LITTLE_ENDIAN) { return ((ch2 << 8) + (ch1)); } else if (mByteOrder == BIG_ENDIAN) { Loading @@ -2166,8 +2215,9 @@ public class ExifInterface { public long readLong() throws IOException { mPosition += 8; if (mPosition > mLength) if (mPosition > mLength) { throw new EOFException(); } int ch1 = super.read(); int ch2 = super.read(); int ch3 = super.read(); Loading @@ -2176,8 +2226,9 @@ public class ExifInterface { int ch6 = super.read(); int ch7 = super.read(); int ch8 = super.read(); if ((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0) if ((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0) { throw new EOFException(); } if (mByteOrder == LITTLE_ENDIAN) { return (((long) ch8 << 56) + ((long) ch7 << 48) + ((long) ch6 << 40) + ((long) ch5 << 32) + ((long) ch4 << 24) + ((long) ch3 << 16) Loading