This is an automated email from the ASF dual-hosted git repository.
Kriskras99 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/avro-rs.git
The following commit(s) were added to refs/heads/main by this push:
new 974efd4 Validate negative OCF block size before conversion (#586)
974efd4 is described below
commit 974efd4edbccde55ec4849ffebec19054c40537a
Author: MitNarodia <[email protected]>
AuthorDate: Tue Jul 14 15:15:01 2026 +0530
Validate negative OCF block size before conversion (#586)
* Validate negative OCF block size before conversion
* Prefix the test name with the pr number
* fix: Require positive block length
* chore: Explain raw bytes
* chore: rename `read_ulong` to `read_usize`
---------
Co-authored-by: Mit Narodia <[email protected]>
Co-authored-by: Martin Grigorov <[email protected]>
Co-authored-by: Kriskras99 <[email protected]>
---
avro/src/reader/block.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++----
avro/src/util.rs | 6 +++--
2 files changed, 57 insertions(+), 6 deletions(-)
diff --git a/avro/src/reader/block.rs b/avro/src/reader/block.rs
index 8899c3a..5e9ae1b 100644
--- a/avro/src/reader/block.rs
+++ b/avro/src/reader/block.rs
@@ -142,11 +142,11 @@ impl<'r, R: Read> Block<'r, R> {
/// the block. The objects are stored in an internal buffer to the
`Reader`.
fn read_block_next(&mut self) -> AvroResult<()> {
assert!(self.is_empty(), "Expected self to be empty!");
- match util::read_long(&mut self.reader).map_err(Error::into_details) {
+ match util::read_usize(&mut self.reader).map_err(Error::into_details) {
Ok(block_len) => {
- self.message_count = block_len as usize;
- let block_bytes = util::read_long(&mut self.reader)?;
- self.fill_buf(block_bytes as usize)?;
+ self.message_count = block_len;
+ let block_bytes = util::read_usize(&mut self.reader)?;
+ self.fill_buf(block_bytes)?;
let mut marker = [0u8; 16];
self.reader
.read_exact(&mut marker)
@@ -353,3 +353,52 @@ fn read_codec(metadata: &HashMap<String, Value>) ->
AvroResult<Codec> {
result.unwrap_or(Ok(Codec::Null))
}
+
+#[cfg(test)]
+mod tests {
+ use super::Block;
+ use crate::error::Details;
+ use crate::{Codec, Schema};
+
+ #[test]
+ fn avro_rs_586_negative_block_size() {
+ let mut block = Block::<'_, &[u8]> {
+ // Block header with an object count of 1 and a block size of -1
+ reader: &[0x02, 0x01],
+ buf: vec![],
+ buf_idx: 0,
+ message_count: 0,
+ marker: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
+ codec: Codec::Null,
+ writer_schema: Schema::Null,
+ schemata: vec![],
+ user_metadata: Default::default(),
+ names_refs: Default::default(),
+ human_readable: false,
+ };
+
+ let err = block.read_block_next().unwrap_err().into_details();
+ assert!(matches!(err, Details::ConvertI64ToUsize(_, _)));
+ }
+
+ #[test]
+ fn avro_rs_586_negative_block_len() {
+ let mut block = Block::<'_, &[u8]> {
+ // Block header with an object count of -1 and a block size of 0
+ reader: &[0x01, 0x00],
+ buf: vec![],
+ buf_idx: 0,
+ message_count: 0,
+ marker: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
+ codec: Codec::Null,
+ writer_schema: Schema::Null,
+ schemata: vec![],
+ user_metadata: Default::default(),
+ names_refs: Default::default(),
+ human_readable: false,
+ };
+
+ let err = block.read_block_next().unwrap_err().into_details();
+ assert!(matches!(err, Details::ConvertI64ToUsize(_, _)));
+ }
+}
diff --git a/avro/src/util.rs b/avro/src/util.rs
index 8728c9e..090d5c3 100644
--- a/avro/src/util.rs
+++ b/avro/src/util.rs
@@ -73,8 +73,10 @@ impl MapHelper for Map<String, Value> {
}
}
-pub(crate) fn read_long<R: Read>(reader: &mut R) -> AvroResult<i64> {
- zag_i64(reader)
+/// Decode a long from the reader and convert it to a usize.
+pub(crate) fn read_usize<R: Read>(reader: &mut R) -> AvroResult<usize> {
+ let long = zag_i64(reader)?;
+ usize::try_from(long).map_err(|e| Details::ConvertI64ToUsize(e,
long).into())
}
/// Write the number as a zigzagged varint to the writer.