mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-03 11:35:29 -04:00
#713 PSD: Broken uncompressed reading from stream w/unknown length
(cherry picked from commit da800be8c8d422321d0f23f04e8e72b1b4c79117)
This commit is contained in:
parent
1e981242ad
commit
0538db7103
@ -53,20 +53,20 @@ public final class SubImageInputStream extends ImageInputStreamImpl {
|
|||||||
/**
|
/**
|
||||||
* Creates a {@link ImageInputStream}, reading up to a maximum number of bytes from the underlying stream.
|
* Creates a {@link ImageInputStream}, reading up to a maximum number of bytes from the underlying stream.
|
||||||
*
|
*
|
||||||
* @param pStream the underlying stream
|
* @param stream the underlying stream
|
||||||
* @param pLength the maximum length to read from the stream.
|
* @param length the maximum length to read from the stream.
|
||||||
* Note that {@code pStream} may contain less than this maximum number of bytes.
|
* Note that {@code stream} may contain less than this maximum number of bytes.
|
||||||
*
|
*
|
||||||
* @throws IOException if {@code pStream}'s position can't be determined.
|
* @throws IOException if {@code stream}'s position can't be determined.
|
||||||
* @throws IllegalArgumentException if {@code pStream == null} or {@code pLength < 0}
|
* @throws IllegalArgumentException if {@code stream == null} or {@code length < 0}
|
||||||
*/
|
*/
|
||||||
public SubImageInputStream(final ImageInputStream pStream, final long pLength) throws IOException {
|
public SubImageInputStream(final ImageInputStream stream, final long length) throws IOException {
|
||||||
Validate.notNull(pStream, "stream");
|
Validate.notNull(stream, "stream");
|
||||||
Validate.isTrue(pLength >= 0, pLength, "length < 0: %d");
|
Validate.isTrue(length >= 0, length, "length < 0: %d");
|
||||||
|
|
||||||
stream = pStream;
|
this.stream = stream;
|
||||||
startPos = pStream.getStreamPosition();
|
this.startPos = stream.getStreamPosition();
|
||||||
length = pLength;
|
this.length = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
@ -84,14 +84,14 @@ public final class SubImageInputStream extends ImageInputStreamImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
|
public int read(final byte[] bytes, final int off, final int len) throws IOException {
|
||||||
if (streamPos >= length) { // Local EOF
|
if (streamPos >= length) { // Local EOF
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safe cast, as pLength can never cause int overflow
|
// Safe cast, as len can never cause int overflow
|
||||||
int length = (int) Math.min(pLength, this.length - streamPos);
|
int length = (int) Math.min(len, this.length - streamPos);
|
||||||
int count = stream.read(pBytes, pOffset, length);
|
int count = stream.read(bytes, off, length);
|
||||||
|
|
||||||
if (count >= 0) {
|
if (count >= 0) {
|
||||||
streamPos += count;
|
streamPos += count;
|
||||||
@ -113,18 +113,18 @@ public final class SubImageInputStream extends ImageInputStreamImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void seek(final long pPosition) throws IOException {
|
public void seek(final long position) throws IOException {
|
||||||
if (pPosition < getFlushedPosition()) {
|
if (position < getFlushedPosition()) {
|
||||||
throw new IndexOutOfBoundsException("pos < flushedPosition");
|
throw new IndexOutOfBoundsException("pos < flushedPosition");
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.seek(startPos + pPosition);
|
stream.seek(startPos + position);
|
||||||
streamPos = pPosition;
|
streamPos = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"FinalizeDoesntCallSuperFinalize"})
|
@SuppressWarnings("MethodDoesntCallSuperMethod")
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() {
|
||||||
// Empty finalizer (for improved performance; no need to call super.finalize() in this case)
|
// Empty finalizer (for improved performance; no need to call super.finalize() in this case)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,8 @@ final class PSDUtil {
|
|||||||
final int[] byteCounts, long compressedLength) throws IOException {
|
final int[] byteCounts, long compressedLength) throws IOException {
|
||||||
switch (compression) {
|
switch (compression) {
|
||||||
case PSD.COMPRESSION_NONE:
|
case PSD.COMPRESSION_NONE:
|
||||||
return new SubImageInputStream(stream, stream.length());
|
long streamLength = stream.length();
|
||||||
|
return new SubImageInputStream(stream, streamLength < 0 ? Long.MAX_VALUE : streamLength);
|
||||||
|
|
||||||
case PSD.COMPRESSION_RLE:
|
case PSD.COMPRESSION_RLE:
|
||||||
return new DirectImageInputStream(new SequenceInputStream(new LazyPackBitsStreamEnumeration(byteCounts, stream)));
|
return new DirectImageInputStream(new SequenceInputStream(new LazyPackBitsStreamEnumeration(byteCounts, stream)));
|
||||||
|
@ -31,10 +31,12 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.psd;
|
package com.twelvemonkeys.imageio.plugins.psd;
|
||||||
|
|
||||||
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
||||||
|
import com.twelvemonkeys.imageio.stream.DirectImageInputStream;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static com.twelvemonkeys.imageio.plugins.psd.PSDUtil.createDecompressorStream;
|
import static com.twelvemonkeys.imageio.plugins.psd.PSDUtil.createDecompressorStream;
|
||||||
@ -65,6 +67,29 @@ public class PSDUtilDecompressorStreamTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUncompressedUnknownLength() throws IOException {
|
||||||
|
// Data represents 3 x 3 raster with 8 bit samples, all 0x7f's
|
||||||
|
byte[] data = new byte[] {
|
||||||
|
0x7f, 0x7f, 0x7f,
|
||||||
|
0x7f, 0x7f, 0x7f,
|
||||||
|
0x7f, 0x7f, 0x7f
|
||||||
|
};
|
||||||
|
try (ImageInputStream input = createDecompressorStream(new DirectImageInputStream(new ByteArrayInputStream(data)), PSD.COMPRESSION_NONE, 3, 8, null, 9)) {
|
||||||
|
byte[] row = new byte[3];
|
||||||
|
|
||||||
|
for (int y = 0; y < 3; y++) {
|
||||||
|
input.readFully(row);
|
||||||
|
|
||||||
|
for (byte b : row) {
|
||||||
|
assertEquals((byte) 0x7f, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(-1, input.read());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPackBits() throws IOException {
|
public void testPackBits() throws IOException {
|
||||||
// Data represents 3 x 3 raster with 8 bit samples, all 42's
|
// Data represents 3 x 3 raster with 8 bit samples, all 42's
|
||||||
|
Loading…
x
Reference in New Issue
Block a user