mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-04 03:55:28 -04:00
#393: Input size validation of ICC profiles
This commit is contained in:
parent
719b6e7883
commit
cd9f3a036e
@ -65,7 +65,6 @@ final class KCMSSanitizerStrategy implements ICCProfileSanitizer {
|
|||||||
((array[index + 3] & 0xff) );
|
((array[index + 3] & 0xff) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: Move to some common util
|
// TODO: Move to some common util
|
||||||
static void intToBigEndian(final int value, final byte[] array, final int index) {
|
static void intToBigEndian(final int value, final byte[] array, final int index) {
|
||||||
array[index ] = (byte) (value >> 24);
|
array[index ] = (byte) (value >> 24);
|
||||||
|
@ -689,7 +689,16 @@ public final class JPEGImageReader extends ImageReaderBase {
|
|||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void intToBigEndian(int value, byte[] array, int index) {
|
// TODO: Move to some common util
|
||||||
|
static int intFromBigEndian(final byte[] array, final int index) {
|
||||||
|
return ((array[index ] & 0xff) << 24) |
|
||||||
|
((array[index + 1] & 0xff) << 16) |
|
||||||
|
((array[index + 2] & 0xff) << 8) |
|
||||||
|
((array[index + 3] & 0xff) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Move to some common util
|
||||||
|
static void intToBigEndian(final int value, final byte[] array, final int index) {
|
||||||
array[index ] = (byte) (value >> 24);
|
array[index ] = (byte) (value >> 24);
|
||||||
array[index + 1] = (byte) (value >> 16);
|
array[index + 1] = (byte) (value >> 16);
|
||||||
array[index + 2] = (byte) (value >> 8);
|
array[index + 2] = (byte) (value >> 8);
|
||||||
@ -853,7 +862,10 @@ public final class JPEGImageReader extends ImageReaderBase {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return readICCProfileSafe(stream, allowBadIndexes);
|
int iccChunkDataSize = segment.data.length - segment.identifier.length() - 3; // ICC_PROFILE + null + chunk number + count
|
||||||
|
int iccSize = intFromBigEndian(segment.data, segment.identifier.length() + 3);
|
||||||
|
|
||||||
|
return readICCProfileSafe(stream, allowBadIndexes, iccSize, iccChunkDataSize);
|
||||||
}
|
}
|
||||||
else if (!segments.isEmpty()) {
|
else if (!segments.isEmpty()) {
|
||||||
// NOTE: This is probably over-complicated, as I've never encountered ICC_PROFILE chunks out of order...
|
// NOTE: This is probably over-complicated, as I've never encountered ICC_PROFILE chunks out of order...
|
||||||
@ -888,25 +900,40 @@ public final class JPEGImageReader extends ImageReaderBase {
|
|||||||
InputStream[] streams = new InputStream[count];
|
InputStream[] streams = new InputStream[count];
|
||||||
streams[badICC ? 0 : chunkNumber - 1] = stream;
|
streams[badICC ? 0 : chunkNumber - 1] = stream;
|
||||||
|
|
||||||
|
int iccChunkDataSize = 0;
|
||||||
|
int iccSize = 0;
|
||||||
|
|
||||||
for (int i = 1; i < count; i++) {
|
for (int i = 1; i < count; i++) {
|
||||||
stream = new DataInputStream(segments.get(i).data());
|
Application segment = segments.get(i);
|
||||||
|
stream = new DataInputStream(segment.data());
|
||||||
|
|
||||||
chunkNumber = stream.readUnsignedByte();
|
chunkNumber = stream.readUnsignedByte();
|
||||||
|
|
||||||
if (!badICC && stream.readUnsignedByte() != chunkCount) {
|
if (stream.readUnsignedByte() != chunkCount && !badICC) {
|
||||||
throw new IIOException(String.format("Bad number of 'ICC_PROFILE' chunks: %d of %d.", chunkNumber, chunkCount));
|
throw new IIOException(String.format("Bad number of 'ICC_PROFILE' chunks: %d of %d.", chunkNumber, chunkCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
streams[badICC ? i : chunkNumber - 1] = stream;
|
int index = badICC ? i : chunkNumber - 1;
|
||||||
|
streams[index] = stream;
|
||||||
|
|
||||||
|
iccChunkDataSize += segment.data.length - segment.identifier.length() - 3;
|
||||||
|
if (index == 0) {
|
||||||
|
iccSize = intFromBigEndian(segment.data, segment.identifier.length() + 3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return readICCProfileSafe(new SequenceInputStream(Collections.enumeration(Arrays.asList(streams))), allowBadIndexes);
|
return readICCProfileSafe(new SequenceInputStream(Collections.enumeration(Arrays.asList(streams))), allowBadIndexes, iccSize, iccChunkDataSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ICC_Profile readICCProfileSafe(final InputStream stream, final boolean allowBadProfile) throws IOException {
|
private ICC_Profile readICCProfileSafe(final InputStream stream, final boolean allowBadProfile, final int iccSize, final int iccChunkDataSize) throws IOException {
|
||||||
|
if (iccSize < 0 || iccSize > iccChunkDataSize) {
|
||||||
|
processWarningOccurred(String.format("Truncated 'ICC_PROFILE' chunk(s), size: %d. Ignoring ICC profile.", iccSize));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ICC_Profile profile = ICC_Profile.getInstance(stream);
|
ICC_Profile profile = ICC_Profile.getInstance(stream);
|
||||||
|
|
||||||
|
@ -2205,6 +2205,13 @@ public final class TIFFImageReader extends ImageReaderBase {
|
|||||||
if (entry != null) {
|
if (entry != null) {
|
||||||
byte[] value = (byte[]) entry.getValue();
|
byte[] value = (byte[]) entry.getValue();
|
||||||
|
|
||||||
|
// Validate ICC profile size vs actual value size
|
||||||
|
int size = (value[0] & 0xff) << 24 | (value[1] & 0xff) << 16 | (value[2] & 0xff) << 8 | (value[3] & 0xff);
|
||||||
|
if (size < 0 || size > value.length) {
|
||||||
|
processWarningOccurred("Ignoring truncated ICC profile: Bad ICC profile size (" + size + ")");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// WEIRDNESS: Reading profile from InputStream is somehow more compatible
|
// WEIRDNESS: Reading profile from InputStream is somehow more compatible
|
||||||
// than reading from byte array (chops off extra bytes + validates profile).
|
// than reading from byte array (chops off extra bytes + validates profile).
|
||||||
@ -2218,7 +2225,6 @@ public final class TIFFImageReader extends ImageReaderBase {
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canReadRaster() {
|
public boolean canReadRaster() {
|
||||||
return true;
|
return true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user