diff --git a/cutile-rs/cutile-ir/src/bytecode/decoder.rs b/cutile-rs/cutile-ir/src/bytecode/decoder.rs index c9d43640f4..956bc372ee 100644 --- a/cutile-rs/cutile-ir/src/bytecode/decoder.rs +++ b/cutile-rs/cutile-ir/src/bytecode/decoder.rs @@ -731,7 +731,7 @@ fn parse_constant_section(payload: Option<&[u8]>) -> Result>> { // Offsets are u64 LE (raw array), not varints. let bytes = r.read_bytes(8)?; let v = u64::from_le_bytes(bytes.try_into().unwrap()); - offsets.push(v as usize); + offsets.push(usize::try_from(v).map_err(|_| err("constant offset out of range"))?); } let const_data = r.read_bytes(r.remaining())?; @@ -743,6 +743,9 @@ fn parse_constant_section(payload: Option<&[u8]>) -> Result>> { } else { const_data.len() }; + if start > end || end > const_data.len() { + return Err(err("constant offsets out of range")); + } constants.push(const_data[start..end].to_vec()); } Ok(constants) @@ -927,4 +930,18 @@ mod tests { assert!(out.contains("\"hello\"")); assert!(out.contains("\"world\"")); } + + #[test] + fn reject_constant_offset_out_of_range() { + let mut section = EncodingWriter::new(); + section.write_varint(1); + section.align_to(8); + section.write_le_u64(2); + section.write_byte(0xaa); + + let error = parse_constant_section(Some(section.as_bytes())) + .unwrap_err() + .to_string(); + assert!(error.contains("constant offsets out of range")); + } }