8154093: [TIFF] NPE when reading LZW-compressed image
authorbpb
Fri, 04 Nov 2016 15:31:38 -0700
changeset 42197 3fa9da09d5b6
parent 42196 3b24ceb9fd89
child 42198 6ff366cc096b
8154093: [TIFF] NPE when reading LZW-compressed image Summary: LZW decompressor was ignoring the value of the FillOrder field. Reviewed-by: prr
jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxDecompressor.java
jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java
jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java
--- 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;
         }
     }
 }