8154093: [TIFF] NPE when reading LZW-compressed image
Summary: LZW decompressor was ignoring the value of the FillOrder field.
Reviewed-by: prr
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxDecompressor.java Fri Nov 04 21:55:19 2016 +0530
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxDecompressor.java Fri Nov 04 15:31:38 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -101,7 +101,8 @@
0xff // 8
};
- // Table to be used when fillOrder = 2, for flipping bytes.
+ // Table to be used for flipping bytes when fillOrder is
+ // BaselineTIFFTagSet.FILL_ORDER_RIGHT_TO_LEFT (2).
static byte flipTable[] = {
0, -128, 64, -64, 32, -96, 96, -32,
16, -112, 80, -48, 48, -80, 112, -16,
@@ -597,7 +598,8 @@
TIFFField f;
f = tmetadata.getTIFFField(BaselineTIFFTagSet.TAG_FILL_ORDER);
- this.fillOrder = f == null ? 1 : f.getAsInt(0);
+ this.fillOrder = f == null ?
+ BaselineTIFFTagSet.FILL_ORDER_LEFT_TO_RIGHT : f.getAsInt(0);
f = tmetadata.getTIFFField(BaselineTIFFTagSet.TAG_COMPRESSION);
this.compression = f == null ?
@@ -612,7 +614,7 @@
f = tmetadata.getTIFFField(BaselineTIFFTagSet.TAG_T6_OPTIONS);
this.t6Options = f == null ? 0 : f.getAsInt(0);
} else {
- this.fillOrder = 1; // MSB-to-LSB
+ this.fillOrder = BaselineTIFFTagSet.FILL_ORDER_LEFT_TO_RIGHT;
this.compression = BaselineTIFFTagSet.COMPRESSION_CCITT_RLE; // RLE
@@ -1458,7 +1460,7 @@
int l = data.length - 1;
int bp = this.bytePointer;
- if (fillOrder == 1) {
+ if (fillOrder == BaselineTIFFTagSet.FILL_ORDER_LEFT_TO_RIGHT) {
b = data[bp];
if (bp == l) {
@@ -1471,7 +1473,7 @@
next = data[bp + 1];
next2next = data[bp + 2];
}
- } else if (fillOrder == 2) {
+ } else if (fillOrder == BaselineTIFFTagSet.FILL_ORDER_RIGHT_TO_LEFT) {
b = flipTable[data[bp] & 0xff];
if (bp == l) {
@@ -1527,14 +1529,14 @@
int l = data.length - 1;
int bp = this.bytePointer;
- if (fillOrder == 1) {
+ if (fillOrder == BaselineTIFFTagSet.FILL_ORDER_LEFT_TO_RIGHT) {
b = data[bp];
if (bp == l) {
next = 0x00;
} else {
next = data[bp + 1];
}
- } else if (fillOrder == 2) {
+ } else if (fillOrder == BaselineTIFFTagSet.FILL_ORDER_RIGHT_TO_LEFT) {
b = flipTable[data[bp] & 0xff];
if (bp == l) {
next = 0x00;
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java Fri Nov 04 21:55:19 2016 +0530
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java Fri Nov 04 15:31:38 2016 -0700
@@ -1174,7 +1174,14 @@
int predictor = ((predictorField == null)
? BaselineTIFFTagSet.PREDICTOR_NONE
: predictorField.getAsInt(0));
- this.decompressor = new TIFFLZWDecompressor(predictor);
+
+ TIFFField fillOrderField
+ = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_FILL_ORDER);
+ int fillOrder = ((fillOrderField == null)
+ ? BaselineTIFFTagSet.FILL_ORDER_LEFT_TO_RIGHT
+ : fillOrderField.getAsInt(0));
+
+ this.decompressor = new TIFFLZWDecompressor(predictor, fillOrder);
} else if (compression
== BaselineTIFFTagSet.COMPRESSION_JPEG) {
this.decompressor = new TIFFJPEGDecompressor();
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java Fri Nov 04 21:55:19 2016 +0530
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java Fri Nov 04 15:31:38 2016 -0700
@@ -30,6 +30,10 @@
class TIFFLZWDecompressor extends TIFFDecompressor {
+ private static final int CLEAR_CODE = 256;
+ private static final int EOI_CODE = 257;
+ private static final int FIRST_CODE = 258;
+
private static final int andTable[] = {
511,
1023,
@@ -39,6 +43,10 @@
private int predictor;
+ // whether to reverse the bits in each byte of the input data, i.e.,
+ // convert right-to-left fill order (lsb) to left-to-right (msb).
+ private boolean flipBits;
+
private byte[] srcData;
private byte[] dstData;
@@ -51,7 +59,8 @@
private int nextData = 0;
private int nextBits = 0;
- public TIFFLZWDecompressor(int predictor) throws IIOException {
+ public TIFFLZWDecompressor(int predictor, int fillOrder)
+ throws IIOException {
super();
if (predictor != BaselineTIFFTagSet.PREDICTOR_NONE &&
@@ -62,6 +71,8 @@
}
this.predictor = predictor;
+
+ flipBits = fillOrder == BaselineTIFFTagSet.FILL_ORDER_RIGHT_TO_LEFT;
}
public void decodeRaw(byte[] b,
@@ -88,6 +99,12 @@
byte[] sdata = new byte[byteCount];
stream.readFully(sdata);
+ if (flipBits) {
+ for (int i = 0; i < byteCount; i++) {
+ sdata[i] = TIFFFaxDecompressor.flipTable[sdata[i] & 0xff];
+ }
+ }
+
int bytesPerRow = (srcWidth*bitsPerPixel + 7)/8;
byte[] buf;
int bufOffset;
@@ -133,11 +150,11 @@
int code, oldCode = 0;
byte[] string;
- while ((code = getNextCode()) != 257) {
- if (code == 256) {
+ while ((code = getNextCode()) != EOI_CODE) {
+ if (code == CLEAR_CODE) {
initializeStringTable();
code = getNextCode();
- if (code == 257) {
+ if (code == EOI_CODE) {
break;
}
@@ -186,12 +203,12 @@
public void initializeStringTable() {
stringTable = new byte[4096][];
- for (int i = 0; i < 256; i++) {
+ for (int i = 0; i < CLEAR_CODE; i++) {
stringTable[i] = new byte[1];
stringTable[i][0] = (byte)i;
}
- tableIndex = 258;
+ tableIndex = FIRST_CODE;
bitsToGet = 9;
}
@@ -281,7 +298,7 @@
return code;
} catch (ArrayIndexOutOfBoundsException e) {
// Strip not terminated as expected: return EndOfInformation code.
- return 257;
+ return EOI_CODE;
}
}
}