8274096: Improve decoding of image files

Reviewed-by: prr, kizune, rhalade, mschoene
This commit is contained in:
Jayathirth D V 2021-10-11 15:52:40 +00:00 committed by Henry Jen
parent 3603e754ce
commit 82d6afe675
6 changed files with 66 additions and 15 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2021, 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
@ -28,6 +28,8 @@ package com.sun.imageio.plugins.common;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import javax.imageio.stream.ImageInputStream;
/**
@ -213,4 +215,47 @@ public class ReaderUtil {
}
return result;
}
/**
* An utility method to allocate and initialize a byte array
* step by step with pre-defined limit, instead of allocating
* a large array up-front based on the length derived from
* an image header.
*
* @param iis a {@code ImageInputStream} to decode data and store
* it in byte array.
* @param length the size of data to decode
*
* @return array of size length when decode succeeeds
*
* @throws IOException if decoding of stream fails
*/
public static byte[] staggeredReadByteStream(ImageInputStream iis,
int length) throws IOException {
final int UNIT_SIZE = 1024000;
byte[] decodedData;
if (length < UNIT_SIZE) {
decodedData = new byte[length];
iis.readFully(decodedData, 0, length);
} else {
int bytesToRead = length;
int bytesRead = 0;
List<byte[]> bufs = new ArrayList<>();
while (bytesToRead != 0) {
int sz = Math.min(bytesToRead, UNIT_SIZE);
byte[] unit = new byte[sz];
iis.readFully(unit, 0, sz);
bufs.add(unit);
bytesRead += sz;
bytesToRead -= sz;
}
decodedData = new byte[bytesRead];
int copiedBytes = 0;
for (byte[] ba : bufs) {
System.arraycopy(ba, 0, decodedData, copiedBytes, ba.length);
copiedBytes += ba.length;
}
}
return decodedData;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2021, 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
@ -1438,7 +1438,11 @@ public abstract class TIFFDecompressor {
*
* @param byteCount the number of bytes of compressed data.
*/
public void setByteCount(int byteCount) {
public void setByteCount(int byteCount) throws IOException{
if (byteCount < 0) {
throw new IIOException("Strip byte count can't be"
+ " negative: " + byteCount);
}
this.byteCount = byteCount;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2021, 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
@ -29,6 +29,7 @@ import java.io.EOFException;
import javax.imageio.IIOException;
import javax.imageio.plugins.tiff.BaselineTIFFTagSet;
import javax.imageio.plugins.tiff.TIFFField;
import com.sun.imageio.plugins.common.ReaderUtil;
class TIFFFaxDecompressor extends TIFFDecompressor {
@ -637,14 +638,14 @@ class TIFFFaxDecompressor extends TIFFDecompressor {
this.bitsPerScanline = scanlineStride*8;
this.lineBitNum = 8*dstOffset;
this.data = new byte[byteCount];
this.bitPointer = 0;
this.bytePointer = 0;
this.prevChangingElems = new int[w + 1];
this.currChangingElems = new int[w + 1];
stream.seek(offset);
stream.readFully(data);
this.data = ReaderUtil.
staggeredReadByteStream(stream, byteCount);
if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_RLE) {
decodeRLE();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2021, 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
@ -27,6 +27,7 @@ package com.sun.imageio.plugins.tiff;
import java.io.IOException;
import javax.imageio.IIOException;
import javax.imageio.plugins.tiff.BaselineTIFFTagSet;
import com.sun.imageio.plugins.common.ReaderUtil;
class TIFFLZWDecompressor extends TIFFDecompressor {
@ -95,9 +96,8 @@ class TIFFLZWDecompressor extends TIFFDecompressor {
}
stream.seek(offset);
byte[] sdata = new byte[byteCount];
stream.readFully(sdata);
byte[] sdata = ReaderUtil.
staggeredReadByteStream(stream, byteCount);
if (flipBits) {
for (int i = 0; i < byteCount; i++) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2021, 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
@ -25,6 +25,7 @@
package com.sun.imageio.plugins.tiff;
import java.io.IOException;
import com.sun.imageio.plugins.common.ReaderUtil;
public class TIFFPackBitsDecompressor extends TIFFDecompressor {
@ -77,8 +78,8 @@ public class TIFFPackBitsDecompressor extends TIFFDecompressor {
int scanlineStride) throws IOException {
stream.seek(offset);
byte[] srcData = new byte[byteCount];
stream.readFully(srcData);
byte[] srcData = ReaderUtil.
staggeredReadByteStream(stream, byteCount);
int bytesPerRow = (srcWidth*bitsPerPixel + 7)/8;
byte[] buf;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2021, 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
@ -180,7 +180,7 @@ public class TIFFYCbCrDecompressor extends TIFFDecompressor {
super.setOffset(offset);
}
public void setByteCount(int byteCount) {
public void setByteCount(int byteCount) throws IOException {
if(decompressor != null) {
decompressor.setByteCount(byteCount);
}