#595 Avoid infinite loop on corrupted JPEG stream

(cherry picked from commit ba0bb7b9039ae66a093afdaf67b6b2495ba254dc)
This commit is contained in:
Harald Kuhr 2021-03-06 14:15:44 +01:00
parent 6acdfd3be6
commit af0a3889db
5 changed files with 67 additions and 15 deletions

View File

@ -178,19 +178,7 @@ public final class JPEGImageReader extends ImageReaderBase {
private boolean isLossless() throws IOException {
assertInput();
try {
if (getSOF().marker == JPEG.SOF3) {
return true;
}
}
catch (IIOException e) {
// May happen if no SOF is found, in case we'll just fall through
if (DEBUG) {
e.printStackTrace();
}
}
return false;
return getSOF().marker == JPEG.SOF3;
}
@Override

View File

@ -572,12 +572,17 @@ final class JPEGSegmentImageInputStream extends ImageInputStreamImpl {
@Override
public int read(final ImageInputStream stream) {
return data[pos++] & 0xff;
return data.length > pos ? data[pos++] & 0xff : -1;
}
@Override
public int read(final ImageInputStream stream, byte[] b, int off, int len) {
int length = Math.min(data.length - pos, len);
int dataLeft = data.length - pos;
if (dataLeft <= 0) {
return -1;
}
int length = Math.min(dataLeft, len);
System.arraycopy(data, pos, b, off, length);
pos += length;

View File

@ -61,6 +61,8 @@ import java.util.List;
import java.util.*;
import static com.twelvemonkeys.imageio.util.IIOUtil.lookupProviderByName;
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeNoException;
@ -1959,4 +1961,36 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
reader.dispose();
}
}
@Test(timeout = 1000L)
public void testInfiniteLoopCorrupt() throws IOException {
ImageReader reader = createReader();
try (ImageInputStream iis = ImageIO.createImageInputStream(getClassLoaderResource("/broken-jpeg/110115680-6d6dce80-7d84-11eb-99df-4cb21df3b09f.jpeg"))) {
reader.setInput(iis);
try {
reader.read(0, null);
}
catch (IIOException expected) {
assertThat(expected.getMessage(), allOf(containsString("SOF"), containsString("stream")));
}
}
}
@Test(timeout = 1000L)
public void testInfiniteLoopCorruptRaster() throws IOException {
ImageReader reader = createReader();
try (ImageInputStream iis = ImageIO.createImageInputStream(getClassLoaderResource("/broken-jpeg/110115680-6d6dce80-7d84-11eb-99df-4cb21df3b09f.jpeg"))) {
reader.setInput(iis);
try {
reader.readRaster(0, null);
}
catch (IIOException expected) {
assertThat(expected.getMessage(), allOf(containsString("SOF"), containsString("stream")));
}
}
}
}

View File

@ -228,4 +228,29 @@ public class JPEGSegmentImageInputStreamTest {
assertEquals(-1, iis.read());
assertEquals(0x2012, iis.getStreamPosition());
}
@Test(timeout = 1000L)
public void testInfiniteLoopCorrupt() throws IOException {
try (ImageInputStream stream = new JPEGSegmentImageInputStream(ImageIO.createImageInputStream(getClassLoaderResource("/broken-jpeg/110115680-6d6dce80-7d84-11eb-99df-4cb21df3b09f.jpeg")))) {
long length = 0;
while (stream.read() != -1) {
length++;
}
assertEquals(25504L, length); // Sanity check: same as file size, except..?
}
try (ImageInputStream stream = new JPEGSegmentImageInputStream(ImageIO.createImageInputStream(getClassLoaderResource("/broken-jpeg/110115680-6d6dce80-7d84-11eb-99df-4cb21df3b09f.jpeg")))) {
long length = 0;
byte[] buffer = new byte[1024];
int read;
while ((read = stream.read(buffer)) != -1) {
length += read;
}
assertEquals(25504L, length); // Sanity check: same as file size, except..?
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB