Skip to content

Commit d1fbda6

Browse files
Merge commit from fork
* Fix BoundedInputStream not counting null-bytes Motivation: The `InputStream.read()` method returns the byte value as an `int` in the range 0 to 255. The `BoundedInputStream` has a bug in counting the number of bytes read, where valid 0-bytes were not counted toward the limit. Modification: The `BoundedInputStream` is changed to only consider -1 as EOF, which is exactly as documented on `InputStream`. The `BoundedInputStream` is also changed to truncate and allow reads up to the limit, and then only trip the exception when it is at the limit and reads beyond. The `BoundedInputStreamTest` has also been made repeating, because it was already occasionally finding this problem. The test now passes consistently with the fixes. Result: The `BoundedInputStream` now counts all byte values toward the limit. * Add deterministic test * Refine deterministic test --------- Co-authored-by: Chris Vest <[email protected]>
1 parent f844d78 commit d1fbda6

File tree

2 files changed

+38
-9
lines changed

2 files changed

+38
-9
lines changed

common/src/main/java/io/netty/util/internal/BoundedInputStream.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,9 @@ public int read() throws IOException {
4040
checkMaxBytesRead();
4141

4242
int b = super.read();
43-
if (b > 0) {
43+
if (b != -1) {
4444
numRead++;
4545
}
46-
47-
checkMaxBytesRead();
4846
return b;
4947
}
5048

@@ -57,11 +55,9 @@ public int read(byte[] buf, int off, int len) throws IOException {
5755

5856
int b = super.read(buf, off, num);
5957

60-
if (b > 0) {
58+
if (b != -1) {
6159
numRead += b;
6260
}
63-
64-
checkMaxBytesRead();
6561
return b;
6662
}
6763

common/src/test/java/io/netty/util/internal/BoundedInputStreamTest.java

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,22 @@
1515
*/
1616
package io.netty.util.internal;
1717

18+
import org.junit.jupiter.api.RepeatedTest;
1819
import org.junit.jupiter.api.Test;
1920
import org.junit.jupiter.api.function.Executable;
2021

2122
import java.io.ByteArrayInputStream;
2223
import java.io.IOException;
2324
import java.util.Arrays;
2425

26+
import static org.assertj.core.api.Assertions.assertThat;
2527
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
2628
import static org.junit.jupiter.api.Assertions.assertEquals;
2729
import static org.junit.jupiter.api.Assertions.assertThrows;
2830

2931
public class BoundedInputStreamTest {
3032

31-
@Test
33+
@RepeatedTest(50)
3234
void testBoundEnforced() throws IOException {
3335
final byte[] bytes = new byte[64];
3436
PlatformDependent.threadLocalRandom().nextBytes(bytes);
@@ -38,19 +40,50 @@ void testBoundEnforced() throws IOException {
3840
assertThrows(IOException.class, new Executable() {
3941
@Override
4042
public void execute() throws Throwable {
41-
reader.read(new byte[64], 0, 64);
43+
int max = bytes.length;
44+
do {
45+
int result = reader.read(new byte[max], 0, max);
46+
assertThat(result).isNotEqualTo(-1);
47+
max -= result;
48+
} while (max > 0);
4249
}
4350
});
4451
reader.close();
4552
}
4653

4754
@Test
55+
void testBoundEnforced256() throws IOException {
56+
final byte[] bytes = new byte[256];
57+
for (int i = 0; i < bytes.length; i++) {
58+
bytes[i] = (byte) i;
59+
}
60+
final BoundedInputStream reader = new BoundedInputStream(new ByteArrayInputStream(bytes), bytes.length - 1);
61+
for (byte expectedByte : bytes) {
62+
assertEquals(expectedByte, (byte) reader.read());
63+
}
64+
65+
assertThrows(IOException.class, new Executable() {
66+
@Override
67+
public void execute() throws Throwable {
68+
reader.read();
69+
}
70+
});
71+
assertThrows(IOException.class, new Executable() {
72+
@Override
73+
public void execute() throws Throwable {
74+
reader.read(new byte[1], 0, 1);
75+
}
76+
});
77+
reader.close();
78+
}
79+
80+
@RepeatedTest(50)
4881
void testBigReadsPermittedIfUnderlyingStreamIsSmall() throws IOException {
4982
final byte[] bytes = new byte[64];
5083
PlatformDependent.threadLocalRandom().nextBytes(bytes);
5184
final BoundedInputStream reader = new BoundedInputStream(new ByteArrayInputStream(bytes), 8192);
5285
final byte[] buffer = new byte[10000];
53-
reader.read(buffer, 0, 10000);
86+
assertThat(reader.read(buffer, 0, 10000)).isEqualTo(64);
5487
assertArrayEquals(bytes, Arrays.copyOfRange(buffer, 0, 64));
5588
reader.close();
5689
}

0 commit comments

Comments
 (0)