#606: Fix bug introduced by more aggressive readDirect.

This commit is contained in:
Harald Kuhr 2021-04-29 20:06:36 +02:00
parent d0c4a07556
commit 4e2bf131d2
2 changed files with 180 additions and 156 deletions

View File

@ -93,8 +93,8 @@ public final class BufferedFileImageInputStream extends ImageInputStreamImpl {
@SuppressWarnings("BooleanMethodIsAlwaysInverted") @SuppressWarnings("BooleanMethodIsAlwaysInverted")
private boolean fillBuffer() throws IOException { private boolean fillBuffer() throws IOException {
bufferPos = 0;
int length = raf.read(buffer, 0, buffer.length); int length = raf.read(buffer, 0, buffer.length);
bufferPos = 0;
bufferLimit = max(length, 0); bufferLimit = max(length, 0);
return bufferLimit > 0; return bufferLimit > 0;
@ -245,7 +245,7 @@ public final class BufferedFileImageInputStream extends ImageInputStreamImpl {
// Optimized to not invalidate buffer if new position is within current buffer // Optimized to not invalidate buffer if new position is within current buffer
long newBufferPos = bufferPos + position - streamPos; long newBufferPos = bufferPos + position - streamPos;
if (newBufferPos >= 0 && newBufferPos <= bufferLimit) { if (newBufferPos >= 0 && newBufferPos < bufferLimit) {
bufferPos = (int) newBufferPos; bufferPos = (int) newBufferPos;
} }
else { else {

View File

@ -67,9 +67,10 @@ public class BufferedFileImageInputStreamTest {
@Test @Test
public void testCreate() throws IOException { public void testCreate() throws IOException {
BufferedFileImageInputStream stream = new BufferedFileImageInputStream(File.createTempFile("empty", ".tmp")); try (BufferedFileImageInputStream stream = new BufferedFileImageInputStream(File.createTempFile("empty", ".tmp"))) {
assertEquals("Data length should be same as stream length", 0, stream.length()); assertEquals("Data length should be same as stream length", 0, stream.length());
} }
}
@Test @Test
public void testCreateNullFile() throws IOException { public void testCreateNullFile() throws IOException {
@ -104,22 +105,21 @@ public class BufferedFileImageInputStreamTest {
byte[] data = new byte[1024 * 1024]; byte[] data = new byte[1024 * 1024];
File file = randomDataToFile(data); File file = randomDataToFile(data);
BufferedFileImageInputStream stream = new BufferedFileImageInputStream(file); try (BufferedFileImageInputStream stream = new BufferedFileImageInputStream(file)) {
assertEquals("File length should be same as stream length", file.length(), stream.length()); assertEquals("File length should be same as stream length", file.length(), stream.length());
for (byte value : data) { for (byte value : data) {
assertEquals("Wrong data read", value & 0xff, stream.read()); assertEquals("Wrong data read", value & 0xff, stream.read());
} }
} }
}
@Test @Test
public void testReadArray() throws IOException { public void testReadArray() throws IOException {
byte[] data = new byte[1024 * 1024]; byte[] data = new byte[1024 * 1024];
File file = randomDataToFile(data); File file = randomDataToFile(data);
BufferedFileImageInputStream stream = new BufferedFileImageInputStream(file); try (BufferedFileImageInputStream stream = new BufferedFileImageInputStream(file)) {
assertEquals("File length should be same as stream length", file.length(), stream.length()); assertEquals("File length should be same as stream length", file.length(), stream.length());
byte[] result = new byte[1024]; byte[] result = new byte[1024];
@ -129,14 +129,14 @@ public class BufferedFileImageInputStreamTest {
assertTrue("Wrong data read: " + i, rangeEquals(data, i * result.length, result, 0, result.length)); assertTrue("Wrong data read: " + i, rangeEquals(data, i * result.length, result, 0, result.length));
} }
} }
}
@Test @Test
public void testReadSkip() throws IOException { public void testReadSkip() throws IOException {
byte[] data = new byte[1024 * 14]; byte[] data = new byte[1024 * 14];
File file = randomDataToFile(data); File file = randomDataToFile(data);
BufferedFileImageInputStream stream = new BufferedFileImageInputStream(file); try (BufferedFileImageInputStream stream = new BufferedFileImageInputStream(file)) {
assertEquals("File length should be same as stream length", file.length(), stream.length()); assertEquals("File length should be same as stream length", file.length(), stream.length());
byte[] result = new byte[7]; byte[] result = new byte[7];
@ -147,14 +147,14 @@ public class BufferedFileImageInputStreamTest {
assertTrue("Wrong data read: " + i, rangeEquals(data, i * result.length, result, 0, result.length)); assertTrue("Wrong data read: " + i, rangeEquals(data, i * result.length, result, 0, result.length));
} }
} }
}
@Test @Test
public void testReadSeek() throws IOException { public void testReadSeek() throws IOException {
byte[] data = new byte[1024 * 18]; byte[] data = new byte[1024 * 18];
File file = randomDataToFile(data); File file = randomDataToFile(data);
BufferedFileImageInputStream stream = new BufferedFileImageInputStream(file); try (BufferedFileImageInputStream stream = new BufferedFileImageInputStream(file)) {
assertEquals("File length should be same as stream length", file.length(), stream.length()); assertEquals("File length should be same as stream length", file.length(), stream.length());
byte[] result = new byte[9]; byte[] result = new byte[9];
@ -168,6 +168,23 @@ public class BufferedFileImageInputStreamTest {
assertTrue("Wrong data read: " + i, rangeEquals(data, (int) newPos, result, 0, result.length)); assertTrue("Wrong data read: " + i, rangeEquals(data, (int) newPos, result, 0, result.length));
} }
} }
}
@Test
public void testReadOutsideDataSeek0Read() throws IOException {
byte[] data = new byte[256];
File file = randomDataToFile(data);
try (BufferedFileImageInputStream stream = new BufferedFileImageInputStream(file)) {
assertEquals("File length should be same as stream length", file.length(), stream.length());
byte[] buffer = new byte[data.length * 2];
stream.read(buffer);
stream.seek(0);
assertNotEquals(-1, stream.read());
assertNotEquals(-1, stream.read(buffer));
}
}
@Test @Test
public void testReadBitRandom() throws IOException { public void testReadBitRandom() throws IOException {
@ -176,12 +193,12 @@ public class BufferedFileImageInputStreamTest {
long value = ByteBuffer.wrap(bytes).getLong(); long value = ByteBuffer.wrap(bytes).getLong();
// Create stream // Create stream
ImageInputStream stream = new BufferedFileImageInputStream(file); try (ImageInputStream stream = new BufferedFileImageInputStream(file)) {
for (int i = 1; i <= 64; i++) { for (int i = 1; i <= 64; i++) {
assertEquals(String.format("bit %d differ", i), (value << (i - 1L)) >>> 63L, stream.readBit()); assertEquals(String.format("bit %d differ", i), (value << (i - 1L)) >>> 63L, stream.readBit());
} }
} }
}
@Test @Test
public void testReadBitsRandom() throws IOException { public void testReadBitsRandom() throws IOException {
@ -190,14 +207,14 @@ public class BufferedFileImageInputStreamTest {
long value = ByteBuffer.wrap(bytes).getLong(); long value = ByteBuffer.wrap(bytes).getLong();
// Create stream // Create stream
ImageInputStream stream = new BufferedFileImageInputStream(file); try (ImageInputStream stream = new BufferedFileImageInputStream(file)) {
for (int i = 1; i <= 64; i++) { for (int i = 1; i <= 64; i++) {
stream.seek(0); stream.seek(0);
assertEquals(String.format("bit %d differ", i), value >>> (64L - i), stream.readBits(i)); assertEquals(String.format("bit %d differ", i), value >>> (64L - i), stream.readBits(i));
assertEquals(i % 8, stream.getBitOffset()); assertEquals(i % 8, stream.getBitOffset());
} }
} }
}
@Test @Test
public void testReadBitsRandomOffset() throws IOException { public void testReadBitsRandomOffset() throws IOException {
@ -206,8 +223,7 @@ public class BufferedFileImageInputStreamTest {
long value = ByteBuffer.wrap(bytes).getLong(); long value = ByteBuffer.wrap(bytes).getLong();
// Create stream // Create stream
ImageInputStream stream = new BufferedFileImageInputStream(file); try (ImageInputStream stream = new BufferedFileImageInputStream(file)) {
for (int i = 1; i <= 60; i++) { for (int i = 1; i <= 60; i++) {
stream.seek(0); stream.seek(0);
stream.setBitOffset(i % 8); stream.setBitOffset(i % 8);
@ -215,13 +231,15 @@ public class BufferedFileImageInputStreamTest {
assertEquals(i * 2 % 8, stream.getBitOffset()); assertEquals(i * 2 % 8, stream.getBitOffset());
} }
} }
}
@Test @Test
public void testReadShort() throws IOException { public void testReadShort() throws IOException {
byte[] bytes = new byte[8743]; // Slightly more than one buffer size byte[] bytes = new byte[8743]; // Slightly more than one buffer size
File file = randomDataToFile(bytes); File file = randomDataToFile(bytes);
ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN); ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN);
final ImageInputStream stream = new BufferedFileImageInputStream(file);
try (final ImageInputStream stream = new BufferedFileImageInputStream(file)) {
stream.setByteOrder(ByteOrder.BIG_ENDIAN); stream.setByteOrder(ByteOrder.BIG_ENDIAN);
for (int i = 0; i < bytes.length / 2; i++) { for (int i = 0; i < bytes.length / 2; i++) {
@ -251,13 +269,15 @@ public class BufferedFileImageInputStreamTest {
} }
}); });
} }
}
@Test @Test
public void testReadInt() throws IOException { public void testReadInt() throws IOException {
byte[] bytes = new byte[8743]; // Slightly more than one buffer size byte[] bytes = new byte[8743]; // Slightly more than one buffer size
File file = randomDataToFile(bytes); File file = randomDataToFile(bytes);
ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN); ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN);
final ImageInputStream stream = new BufferedFileImageInputStream(file);
try (final ImageInputStream stream = new BufferedFileImageInputStream(file)) {
stream.setByteOrder(ByteOrder.BIG_ENDIAN); stream.setByteOrder(ByteOrder.BIG_ENDIAN);
for (int i = 0; i < bytes.length / 4; i++) { for (int i = 0; i < bytes.length / 4; i++) {
@ -287,13 +307,15 @@ public class BufferedFileImageInputStreamTest {
} }
}); });
} }
}
@Test @Test
public void testReadLong() throws IOException { public void testReadLong() throws IOException {
byte[] bytes = new byte[8743]; // Slightly more than one buffer size byte[] bytes = new byte[8743]; // Slightly more than one buffer size
File file = randomDataToFile(bytes); File file = randomDataToFile(bytes);
ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN); ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN);
final ImageInputStream stream = new BufferedFileImageInputStream(file);
try (final ImageInputStream stream = new BufferedFileImageInputStream(file)) {
stream.setByteOrder(ByteOrder.BIG_ENDIAN); stream.setByteOrder(ByteOrder.BIG_ENDIAN);
for (int i = 0; i < bytes.length / 8; i++) { for (int i = 0; i < bytes.length / 8; i++) {
@ -323,13 +345,14 @@ public class BufferedFileImageInputStreamTest {
} }
}); });
} }
}
@Test @Test
public void testSeekPastEOF() throws IOException { public void testSeekPastEOF() throws IOException {
byte[] bytes = new byte[9]; byte[] bytes = new byte[9];
File file = randomDataToFile(bytes); File file = randomDataToFile(bytes);
final ImageInputStream stream = new BufferedFileImageInputStream(file); try (final ImageInputStream stream = new BufferedFileImageInputStream(file)) {
stream.seek(1000); stream.seek(1000);
assertEquals(-1, stream.read()); assertEquals(-1, stream.read());
@ -373,6 +396,7 @@ public class BufferedFileImageInputStreamTest {
assertEquals(-1, stream.read()); assertEquals(-1, stream.read());
} }
}
@Test @Test
public void testClose() throws IOException { public void testClose() throws IOException {