From 178c010f53ec57b20f33b4d7737e0c0775dafe91 Mon Sep 17 00:00:00 2001 From: Tyler Gregg Date: Thu, 2 May 2024 10:49:57 -0700 Subject: [PATCH] Ensures that encountering an incomplete binary IVM causes clean failure. --- .../com/amazon/ion/impl/IonCursorBinary.java | 3 +++ .../amazon/ion/impl/IonCursorBinaryTest.java | 22 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/main/java/com/amazon/ion/impl/IonCursorBinary.java b/src/main/java/com/amazon/ion/impl/IonCursorBinary.java index 4887aca16f..6166cfc381 100644 --- a/src/main/java/com/amazon/ion/impl/IonCursorBinary.java +++ b/src/main/java/com/amazon/ion/impl/IonCursorBinary.java @@ -1113,6 +1113,9 @@ private void reset() { * point to the first byte after the IVM. */ private void readIvm() { + if (limit < peekIndex + IVM_REMAINING_LENGTH) { + throw new IonException("Incomplete Ion version marker."); + } majorVersion = buffer[(int) (peekIndex++)]; minorVersion = buffer[(int) (peekIndex++)]; if ((buffer[(int) (peekIndex++)] & SINGLE_BYTE_MASK) != IVM_FINAL_BYTE) { diff --git a/src/test/java/com/amazon/ion/impl/IonCursorBinaryTest.java b/src/test/java/com/amazon/ion/impl/IonCursorBinaryTest.java index 436bb0030a..38336067bc 100644 --- a/src/test/java/com/amazon/ion/impl/IonCursorBinaryTest.java +++ b/src/test/java/com/amazon/ion/impl/IonCursorBinaryTest.java @@ -13,6 +13,7 @@ import java.util.function.Consumer; import static com.amazon.ion.BitUtils.bytes; +import static com.amazon.ion.IonCursor.Event.NEEDS_DATA; import static com.amazon.ion.IonCursor.Event.VALUE_READY; import static com.amazon.ion.IonCursor.Event.START_CONTAINER; import static com.amazon.ion.IonCursor.Event.START_SCALAR; @@ -445,4 +446,25 @@ public void expectUseAfterCloseToHaveNoEffect(boolean constructFromBytes) { assertNull(cursor.getValueMarker().typeId); cursor.close(); } + + @ParameterizedTest(name = "constructFromBytes={0}") + @ValueSource(booleans = {true, false}) + public void expectIncompleteIvmToFailCleanly(boolean constructFromBytes) { + IonCursorBinary cursor = initializeCursor( + constructFromBytes, + 0xE0, 0x01, 0x00, 0xEA, // Complete IVM + 0x20, // Int 0 + 0xE0, 0x01 // Incomplete IVM + ); + assertEquals(START_SCALAR, cursor.nextValue()); + if (constructFromBytes) { + // This is a fixed stream, so no more bytes will become available. An error must be raised when the + // incomplete IVM is encountered. + assertThrows(IonException.class, cursor::nextValue); + } else { + // This is a growing stream, so the cursor waits for more bytes. + assertEquals(NEEDS_DATA, cursor.nextValue()); + } + cursor.close(); + } }