From 44a025e2492cb046485558c4629eeaa7fcf82b63 Mon Sep 17 00:00:00 2001 From: Tyler Gregg Date: Mon, 5 Aug 2024 17:22:03 -0700 Subject: [PATCH] Adds checks for timestamp values with length 0. --- .../impl/IonReaderContinuableCoreBinary.java | 3 ++ .../IonReaderContinuableCoreBinaryTest.java | 35 ++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/amazon/ion/impl/IonReaderContinuableCoreBinary.java b/src/main/java/com/amazon/ion/impl/IonReaderContinuableCoreBinary.java index 93331bfd31..f0ce3e41be 100644 --- a/src/main/java/com/amazon/ion/impl/IonReaderContinuableCoreBinary.java +++ b/src/main/java/com/amazon/ion/impl/IonReaderContinuableCoreBinary.java @@ -750,6 +750,9 @@ public Timestamp timestampValue() { } prepareScalar(); peekIndex = valueMarker.startIndex; + if (peekIndex >= valueMarker.endIndex) { + throw new IonException("Timestamp value cannot have length 0."); + } return minorVersion == 0 ? readTimestamp_1_0() : readTimestamp_1_1(); } diff --git a/src/test/java/com/amazon/ion/impl/IonReaderContinuableCoreBinaryTest.java b/src/test/java/com/amazon/ion/impl/IonReaderContinuableCoreBinaryTest.java index 2d81d09974..4b5c92fa2e 100644 --- a/src/test/java/com/amazon/ion/impl/IonReaderContinuableCoreBinaryTest.java +++ b/src/test/java/com/amazon/ion/impl/IonReaderContinuableCoreBinaryTest.java @@ -1,6 +1,5 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 - package com.amazon.ion.impl; import com.amazon.ion.IonCursor; @@ -13,6 +12,7 @@ import java.io.ByteArrayInputStream; import static com.amazon.ion.BitUtils.bytes; +import static com.amazon.ion.IonCursor.Event.START_SCALAR; import static com.amazon.ion.impl.IonCursorTestUtilities.STANDARD_BUFFER_CONFIGURATION; import static com.amazon.ion.impl.IonCursorTestUtilities.Expectation; import static com.amazon.ion.impl.IonCursorTestUtilities.ExpectationProvider; @@ -631,4 +631,37 @@ public void expectIncompleteAnnotationHeaderToFailCleanly() { assertThrows(IonException.class, reader::nextValue); reader.close(); } + + @Test + public void timestampLengthZeroAtStreamEndFailsCleanly() { + try ( + IonReaderContinuableCoreBinary reader = initializeReader( + // Note: a refillable reader would await more bytes before throwing. See the next test. + true, + 0xE0, 0x01, 0x00, 0xEA, // IVM + 0x6E, // Timestamp value, variable length. + 0x80 // VarUInt 0 at stream end. This is an error because there is no length 0 timestamp. + ) + ) { + assertEquals(START_SCALAR, reader.nextValue()); + assertThrows(IonException.class, reader::timestampValue); + } + } + + @ParameterizedTest(name = "constructFromBytes={0}") + @ValueSource(booleans = {true, false}) + public void timestampLengthZeroFailsCleanly(boolean constructFromBytes) { + try ( + IonReaderContinuableCoreBinary reader = initializeReader( + constructFromBytes, + 0xE0, 0x01, 0x00, 0xEA, // IVM + 0x6E, // Timestamp value, variable length. + 0x80, // VarUInt 0 at stream end. This is an error because there is no length 0 timestamp. + 0x20 // Value byte to pad the input. A refillable reader expects at least this many bytes to compose a valid timestamp. + ) + ) { + assertEquals(START_SCALAR, reader.nextValue()); + assertThrows(IonException.class, reader::timestampValue); + } + } }