Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/main/java/com/amazon/ion/impl/IonCursorBinary.java
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,9 @@ private long uncheckedReadVarUInt_1_0(byte currentByte) {
currentByte = buffer[(int) (peekIndex++)];
result = (result << VALUE_BITS_PER_VARUINT_BYTE) | (currentByte & LOWER_SEVEN_BITS_BITMASK);
} while (currentByte >= 0);
if (result < 0) {
throw new IonException("Found a VarUInt that was too large to fit in a `long`");
}
return result;
}

Expand Down Expand Up @@ -796,7 +799,7 @@ private boolean uncheckedReadAnnotationWrapperHeader_1_0(IonTypeID valueTid) {
}
endIndex += peekIndex;
setMarker(endIndex, valueMarker);
if (endIndex > limit) {
if (endIndex > limit || endIndex < 0) {
throw new IonException("Malformed data: declared length exceeds the number of bytes remaining in the stream.");
}
byte b = buffer[(int) peekIndex++];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,70 @@ public void expectLobWithOverflowingEndIndexToFailCleanly(boolean constructFromB
reader.close();
}

@Test
public void expectIncompleteAnnotationWrapperWithOverflowingEndIndexToFailCleanly() {
// This test exercises the case where an annotation wrapper's length itself does not overflow a java long,
// but its end index (calculated by adding the reader's current index in the buffer to the value's length) does.
// Note: this is only tested for fixed input sources because non-fixed sources will wait for more input
// to determine if the annotation wrapper is well-formed. The next test tests a similar failure case for
// both types of inputs.
IonReaderContinuableCoreBinary reader = initializeReader(
true,
0xE0, 0x01, 0x00, 0xEA,
0xEE,
0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFE // 9-byte VarUInt with value just below Long.MAX_VALUE
);
assertThrows(IonException.class, reader::nextValue);
reader.close();
}

@ParameterizedTest(name = "constructFromBytes={0}")
@ValueSource(booleans = {true, false})
public void expectCompleteAnnotationWrapperWithOverflowingEndIndexToFailCleanly(boolean constructFromBytes) {
// This test exercises the case where an annotation wrapper's length itself does not overflow a java long,
// but its end index (calculated by adding the reader's current index in the buffer to the value's length) does.
// Unlike the previous test, this test contains the remaining bytes of the annotation wrapper, allowing the
// cursor to advance to a failure condition even when the input is not fixed.
IonReaderContinuableCoreBinary reader = initializeReader(
constructFromBytes,
0xE0, 0x01, 0x00, 0xEA,
0xEE,
0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFE, // 9-byte VarUInt with value just below Long.MAX_VALUE
0x81, 0x83
);
assertThrows(IonException.class, reader::nextValue);
reader.close();
}

@ParameterizedTest(name = "constructFromBytes={0}")
@ValueSource(booleans = {true, false})
public void expectLobWithOverflowingLengthToFailCleanly(boolean constructFromBytes) {
// This test exercises the case where a value's length overflows a java long.
IonReaderContinuableCoreBinary reader = initializeReader(
constructFromBytes,
0xE0, 0x01, 0x00, 0xEA, // IVM
0x9E, // clob with length VarUInt
0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFF, // 10-byte VarUInt with value that exceeds Long.MAX_VALUE
0x00 // The first byte of the clob
);
assertThrows(IonException.class, reader::nextValue);
reader.close();
}

@ParameterizedTest(name = "constructFromBytes={0}")
@ValueSource(booleans = {true, false})
public void expectAnnotationWrapperWithOverflowingLengthToFailCleanly(boolean constructFromBytes) {
// This test exercises the case where an annotation wrapper's length overflows a java long.
IonReaderContinuableCoreBinary reader = initializeReader(
constructFromBytes,
0xE0, 0x01, 0x00, 0xEA,
0xEE,
0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFF // 10-byte VarUInt with value that exceeds Long.MAX_VALUE
);
assertThrows(IonException.class, reader::nextValue);
reader.close();
}

@Test
public void expectIncompleteContainerToFailCleanlyAfterFieldSid() {
IonReaderContinuableCoreBinary reader = initializeReader(
Expand Down