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

Fix multiple blocking binary reader issues #552

Merged
merged 5 commits into from
May 25, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/binary/non_blocking/binary_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -808,4 +808,17 @@ mod tests {
.expect_err("This exceeded the configured max Int size.");
Ok(())
}

#[test]
fn validate_read_from_size() -> IonResult<()> {
// This test validates that the size of data we wish to read, is actually honored by
zslayton marked this conversation as resolved.
Show resolved Hide resolved
// read_from. A bug existed where the sub-slice of the buffer was calculated incorrectly,
// leading to the potential for failed reads, or increasingly smaller reads.
let mut buffer = BinaryBuffer::new(vec![0; 10]);
let new_data: &[u8] = &[0; 11];
let bytes_read = buffer.read_from(new_data, 11)?;
assert_eq!(bytes_read, 11);

Ok(())
}
}
34 changes: 34 additions & 0 deletions src/binary/non_blocking/raw_binary_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2062,4 +2062,38 @@ mod tests {
);
Ok(())
}

#[test]
fn test_incomplete_annotation_wrapper() -> IonResult<()> {
// This test ensures that if we reach the end of the buffer while processing the annotation
// wrapper, we do not try to consume beyond the buffer's limits. Instead, we should get an
// incomplete error so that the data can be skipped properly.

let ion_data = &[
// First top-level value in the stream
0xDB, // 11-byte struct
0x8B, // Field ID 11
0xB6, // 6-byte List
0x21, 0x01, // Integer 1
0x21, 0x02, // Integer 2
0x21, 0x03, // Integer 3
0x8A, // Field ID 10
0x21, 0x01, // Integer 1
// Second top-level value in the stream
0xE3, // 3-byte annotations envelope
0x81, // * Annotations themselves take 1 byte (buffer read stops here)
0x8C, // * Annotation w/SID $12
0x10, // Boolean false
];

let mut cursor = RawBinaryReader::new(&ion_data[0..14]);
assert_eq!(RawStreamItem::Value(IonType::Struct), cursor.next()?);
match cursor.next() {
Err(IonError::Incomplete { .. }) => (),
Err(_) => panic!("Unexpected error"),
Ok(_) => panic!("Successful parse of incomplete data."),
}

Ok(())
}
}
35 changes: 35 additions & 0 deletions src/blocking_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -536,4 +536,39 @@ mod tests {
);
Ok(())
}

#[test]
fn test_binary_end_of_stream() -> IonResult<()> {
// This test is to ensure that the non-blocking binary reader is honoring the end of stream
// flag, and that the blocking reader is making use of it. A previous bug existed where the
// binary reader was not using the end of stream flag, and ending a read on a data boundary
// would result in the blocking reader not providing any more data, since it relies on
// Incomplete errors to do so.

// {$11: [1, 2, 3], $10: 1}
let ion_data: &[u8] = &[
// First top-level value in the stream
0xDB, // 11-byte struct
0x8B, // Field ID 11
0xB6, // 6-byte List
0x21, 0x01, // Integer 1
0x21, 0x02, // Integer 2
0x21, 0x03, // Integer 3
0x8A, // Field ID 10
0x21, 0x01, // Integer 1
// Second top-level value in the stream
0xE3, // 3-byte annotations envelope
0x81, // * Annotations themselves take 1 byte
0x8C, // * Annotation w/SID $12
0x10, // Boolean false
];
// Create a blocking reader with an initial buffer size of 12, so that we can read exactly
// the first value. If EOS is not honored, our second call to `next` should result in no
// value being read, since the blocking reader would not know to provide more data.
let mut cursor = BlockingRawBinaryReader::new_with_size(ion_data.to_owned(), 12)?;
assert_eq!(RawStreamItem::Value(IonType::Struct), cursor.next()?);
assert_eq!(RawStreamItem::Value(IonType::Bool), cursor.next()?);

Ok(())
}
}