Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes a bug that caused the binary reader not to fail cleanly when parsing incomplete containers in certain cases. #710

Merged
merged 1 commit into from
Feb 2, 2024
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
3 changes: 3 additions & 0 deletions src/main/java/com/amazon/ion/impl/IonCursorBinary.java
Original file line number Diff line number Diff line change
Expand Up @@ -1574,6 +1574,9 @@ private boolean uncheckedNextToken() {
if (uncheckedNextContainedToken()) {
return false;
}
if (peekIndex >= limit) {
throw new IonException("Malformed data: declared length exceeds the number of bytes remaining in the container.");
}
b = buffer[(int)(peekIndex++)] & SINGLE_BYTE_MASK;
}
if (uncheckedReadHeader(b, false, valueMarker)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

package com.amazon.ion.impl;

import com.amazon.ion.IonCursor;
import com.amazon.ion.IonException;
import com.amazon.ion.IonType;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -496,4 +497,74 @@ public void expectLobWithOverflowingEndIndexToFailCleanly(boolean constructFromB
assertThrows(IonException.class, reader::nextValue);
reader.close();
}

@Test
public void expectIncompleteContainerToFailCleanlyAfterFieldSid() {
IonReaderContinuableCoreBinary reader = initializeReader(
true,
0xE0, 0x01, 0x00, 0xEA, // IVM
0xDC, // Struct, length 12
0x9A // Field SID 26
// The struct ends unexpectedly
);
assertEquals(IonCursor.Event.START_CONTAINER, reader.nextValue());
assertEquals(IonType.STRUCT, reader.getType());
reader.stepIntoContainer();
// This is an unexpected EOF, so the reader should fail cleanly.
assertThrows(IonException.class, reader::nextValue);
reader.close();
}

@Test
public void expectIncompleteContainerToFailCleanlyAfterTwoByteFieldSid() {
IonReaderContinuableCoreBinary reader = initializeReader(
true,
0xE0, 0x01, 0x00, 0xEA, // IVM
0xDC, // Struct, length 12
0x00, // First byte of overpadded 2-byte field SID
0x9A // Field SID 26
// The struct ends unexpectedly
);
assertEquals(IonCursor.Event.START_CONTAINER, reader.nextValue());
assertEquals(IonType.STRUCT, reader.getType());
reader.stepIntoContainer();
// This is an unexpected EOF, so the reader should fail cleanly.
assertThrows(IonException.class, reader::nextValue);
reader.close();
}

@Test
public void expectIncompleteContainerToFailCleanlyAfterAnnotationHeader() {
IonReaderContinuableCoreBinary reader = initializeReader(
true,
0xE0, 0x01, 0x00, 0xEA, // IVM
0xDC, // Struct, length 12
0x9A, // Field SID 26
0xE4, // Annotation wrapper length 4
0x00, 0x81, // VarUInt length 1 (overpadded by 1 byte)
0x00, 0x84 // VarUInt SID 4 (overpadded by 1 byte)
// The value ends unexpectedly
);
assertEquals(IonCursor.Event.START_CONTAINER, reader.nextValue());
assertEquals(IonType.STRUCT, reader.getType());
reader.stepIntoContainer();
// This is an unexpected EOF, so the reader should fail cleanly.
assertThrows(IonException.class, reader::nextValue);
reader.close();
}

@Test
public void expectIncompleteAnnotationHeaderToFailCleanly() {
IonReaderContinuableCoreBinary reader = initializeReader(
true,
0xE0, 0x01, 0x00, 0xEA, // IVM
0xE4, // Annotation wrapper length 5
0x81, // VarUInt length 1
0x84 // VarUInt SID 4
// The value ends unexpectedly
);
// This is an unexpected EOF, so the reader should fail cleanly.
assertThrows(IonException.class, reader::nextValue);
reader.close();
}
}
Loading