Fix infinite loop in PackedInputStream when the supplied ArrayInputStream is smaller than needed
Additionally: * ArrayInputStream is no longer final, as there is no reason to stop consumers from extending and adjusting the behaviour * The wrapped ByteBuffer is not private, as according to the (previously) undocumented contract, it should be only accessible through #getReadBuffer().
This commit is contained in:
parent
e570a6ce70
commit
de1e334091
3 changed files with 29 additions and 5 deletions
|
@ -23,11 +23,10 @@ package org.capnproto;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.ReadableByteChannel;
|
|
||||||
|
|
||||||
public final class ArrayInputStream implements BufferedInputStream {
|
public class ArrayInputStream implements BufferedInputStream {
|
||||||
|
|
||||||
public final ByteBuffer buf;
|
private final ByteBuffer buf;
|
||||||
|
|
||||||
public ArrayInputStream(ByteBuffer buf) {
|
public ArrayInputStream(ByteBuffer buf) {
|
||||||
this.buf = buf.asReadOnlyBuffer();
|
this.buf = buf.asReadOnlyBuffer();
|
||||||
|
@ -52,7 +51,11 @@ public final class ArrayInputStream implements BufferedInputStream {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final ByteBuffer getReadBuffer() {
|
public final ByteBuffer getReadBuffer() {
|
||||||
return this.buf;
|
if (buf.remaining() > 0) {
|
||||||
|
return buf;
|
||||||
|
} else {
|
||||||
|
throw new DecodeException("Premature EOF while reading buffer");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -25,5 +25,14 @@ import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.ReadableByteChannel;
|
import java.nio.channels.ReadableByteChannel;
|
||||||
|
|
||||||
public interface BufferedInputStream extends ReadableByteChannel {
|
public interface BufferedInputStream extends ReadableByteChannel {
|
||||||
public ByteBuffer getReadBuffer() throws java.io.IOException;
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link ByteBuffer} to read data from.
|
||||||
|
* If there is no more data to read, throws a {@link DecodeException}.
|
||||||
|
*
|
||||||
|
* @return a {@link ByteBuffer} with data to read from, if any available
|
||||||
|
* @throws java.io.IOException when an I/O error occurs
|
||||||
|
* @throws DecodeException when trying to read more data than available
|
||||||
|
*/
|
||||||
|
ByteBuffer getReadBuffer() throws java.io.IOException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,4 +82,16 @@ public class SerializePackedTest {
|
||||||
Assert.assertTrue(Arrays.equals(bytes, unpacked));
|
Assert.assertTrue(Arrays.equals(bytes, unpacked));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 1000, expected = DecodeException.class)
|
||||||
|
public void read_shouldThrowDecodingExceptionOnEmptyArrayInputStream() throws IOException {
|
||||||
|
byte[] emptyByteArray = {};
|
||||||
|
MessageReader reader = SerializePacked.read(new ArrayInputStream(ByteBuffer.wrap(emptyByteArray)), ReaderOptions.DEFAULT_READER_OPTIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 1000, expected = DecodeException.class)
|
||||||
|
public void read_shouldThrowDecodingExceptionWhenTryingToReadMoreThanAvailableFromArrayInputStream() throws IOException {
|
||||||
|
byte[] bytes = {17, 0, 127, 0, 0, 0, 0}; //segment0 size of 127 words, which is way larger than the tiny 7 byte input
|
||||||
|
MessageReader reader = SerializePacked.read(new ArrayInputStream(ByteBuffer.wrap(bytes)), ReaderOptions.DEFAULT_READER_OPTIONS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue