Skip to content

Commit e85547c

Browse files
tgregglinlin-s
authored andcommitted
Fixes handling of annotation wrapper length overflows.
1 parent f78f43d commit e85547c

2 files changed

Lines changed: 59 additions & 3 deletions

File tree

src/main/java/com/amazon/ion/impl/IonCursorBinary.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,9 @@ private long availableAt(long index) {
502502
* @return true if the buffer has sufficient capacity; otherwise, false.
503503
*/
504504
private boolean ensureCapacity(long minimumNumberOfBytesRequired) {
505+
if (minimumNumberOfBytesRequired < 0) {
506+
throw new IonException("The number of bytes required cannot be represented in a Java long.");
507+
}
505508
if (freeSpaceAt(offset) >= minimumNumberOfBytesRequired) {
506509
// No need to shift any bytes or grow the buffer.
507510
return true;
@@ -809,18 +812,21 @@ private boolean uncheckedReadAnnotationWrapperHeader_1_0(IonTypeID valueTid) {
809812
throw new IonException("Malformed data: declared length exceeds the number of bytes remaining in the stream.");
810813
}
811814
byte b = buffer[(int) peekIndex++];
812-
int annotationsLength;
815+
long annotationsLength;
813816
if (b < 0) {
814817
annotationsLength = (b & LOWER_SEVEN_BITS_BITMASK);
815818
} else {
816-
annotationsLength = (int) uncheckedReadVarUInt_1_0(b);
819+
annotationsLength = uncheckedReadVarUInt_1_0(b);
817820
}
818821
annotationSequenceMarker.startIndex = peekIndex;
819822
annotationSequenceMarker.endIndex = annotationSequenceMarker.startIndex + annotationsLength;
820823
peekIndex = annotationSequenceMarker.endIndex;
821824
if (peekIndex >= endIndex) {
822825
throw new IonException("Annotation wrapper must wrap a value.");
823826
}
827+
if (peekIndex < 0) {
828+
throw new IonException("Malformed data: declared length exceeds the number of bytes remaining in the stream.");
829+
}
824830
return false;
825831
}
826832

@@ -855,7 +861,7 @@ private boolean slowReadAnnotationWrapperHeader_1_0(IonTypeID valueTid) {
855861
}
856862
// Record the post-length index in a value that will be shifted in the event the buffer needs to refill.
857863
setMarker(peekIndex + valueLength, valueMarker);
858-
int annotationsLength = (int) slowReadVarUInt_1_0();
864+
long annotationsLength = slowReadVarUInt_1_0();
859865
if (annotationsLength < 0) {
860866
return true;
861867
}

src/test/java/com/amazon/ion/impl/IonCursorBinaryTest.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,4 +467,54 @@ public void expectIncompleteIvmToFailCleanly(boolean constructFromBytes) {
467467
}
468468
cursor.close();
469469
}
470+
471+
@ParameterizedTest(name = "constructFromBytes={0}")
472+
@ValueSource(booleans = {true, false})
473+
public void annotationSequenceLengthExceedsJavaLong(boolean constructFromBytes) {
474+
try (
475+
IonCursorBinary cursor = initializeCursor(
476+
constructFromBytes,
477+
0xE0, 0x01, 0x00, 0xEA, // IVM
478+
0xEA, // Annotation wrapper, length 10
479+
0x01, 0x16, 0x76, 0x76, 0x76, 0x76, 0x3F, 0x3F, 0x76, 0x76, 0xF3, // Annotation sequence length > Long.MAX_VALUE
480+
0x9E // The start of the annotation sequence
481+
)
482+
) {
483+
assertThrows(IonException.class, cursor::nextValue);
484+
}
485+
}
486+
487+
@ParameterizedTest(name = "constructFromBytes={0}")
488+
@ValueSource(booleans = {true, false})
489+
public void annotationSequenceLengthPlusCurrentIndexExceedsJavaLong(boolean constructFromBytes) {
490+
try (
491+
IonCursorBinary cursor = initializeCursor(
492+
constructFromBytes,
493+
0xE0, 0x01, 0x00, 0xEA, // IVM
494+
0xEA, // Annotation wrapper, length 10
495+
0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFF, // Annotation sequence length = Long.MAX_VALUE
496+
0x9E // The start of the annotation sequence
497+
)
498+
) {
499+
assertThrows(IonException.class, cursor::nextValue);
500+
}
501+
}
502+
503+
@ParameterizedTest(name = "constructFromBytes={0}")
504+
@ValueSource(booleans = {true, false})
505+
public void annotationWrapperLengthPlusCurrentIndexExceedsJavaLong(boolean constructFromBytes) {
506+
try (
507+
IonCursorBinary cursor = initializeCursor(
508+
constructFromBytes,
509+
0xE0, 0x01, 0x00, 0xEA, // IVM
510+
0xEE, // Annotation wrapper, variable length
511+
0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFF, // Annotation wrapper length = Long.MAX_VALUE
512+
0x81, // Annotation sequence length = 1
513+
0x83, // SID 3
514+
0x9E // The start of the wrapped value
515+
)
516+
) {
517+
assertThrows(IonException.class, cursor::nextValue);
518+
}
519+
}
470520
}

0 commit comments

Comments
 (0)