From 9ecae6db4874e742db26813ab9d52296fa2fe18e Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Fri, 4 Nov 2016 15:31:38 -0700 Subject: [PATCH] 8154093: [TIFF] NPE when reading LZW-compressed image LZW decompressor was ignoring the value of the FillOrder field. Reviewed-by: prr --- .../plugins/tiff/TIFFFaxDecompressor.java | 18 ++++++----- .../imageio/plugins/tiff/TIFFImageReader.java | 9 +++++- .../plugins/tiff/TIFFLZWDecompressor.java | 31 ++++++++++++++----- 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxDecompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxDecompressor.java index 9d522366d86..c0279b134f8 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxDecompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxDecompressor.java @@ -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 @@ class TIFFFaxDecompressor extends TIFFDecompressor { 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 @@ class TIFFFaxDecompressor extends TIFFDecompressor { 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 @@ class TIFFFaxDecompressor extends TIFFDecompressor { 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 @@ class TIFFFaxDecompressor extends TIFFDecompressor { 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 @@ class TIFFFaxDecompressor extends TIFFDecompressor { 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 @@ class TIFFFaxDecompressor extends TIFFDecompressor { 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; diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java index 0a872faa0c5..91778e7e097 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java @@ -1174,7 +1174,14 @@ public class TIFFImageReader extends ImageReader { 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(); diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java index 340179f7e8d..423b97c8e0a 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java @@ -30,6 +30,10 @@ import javax.imageio.plugins.tiff.BaselineTIFFTagSet; 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 @@ class TIFFLZWDecompressor extends TIFFDecompressor { 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 @@ class TIFFLZWDecompressor extends TIFFDecompressor { 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 @@ class TIFFLZWDecompressor extends TIFFDecompressor { } this.predictor = predictor; + + flipBits = fillOrder == BaselineTIFFTagSet.FILL_ORDER_RIGHT_TO_LEFT; } public void decodeRaw(byte[] b, @@ -88,6 +99,12 @@ class TIFFLZWDecompressor extends TIFFDecompressor { 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 @@ class TIFFLZWDecompressor extends TIFFDecompressor { 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 @@ class TIFFLZWDecompressor extends TIFFDecompressor { 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 @@ class TIFFLZWDecompressor extends TIFFDecompressor { return code; } catch (ArrayIndexOutOfBoundsException e) { // Strip not terminated as expected: return EndOfInformation code. - return 257; + return EOI_CODE; } } }