Hello, thank you for this crate! I've discovered a potential unsoundness that could trigger an Undefined Behavior (OOB) in secure code.
fn main() {
use sfbinpack::CompressedTrainingDataEntryReader;
use std::io::Cursor;
// Safe API UB: CompressedTrainingDataEntryReader constructs a BitReader
// from a raw pointer without tracking length. A crafted chunk with
// num_plies > 0 but no movetext bytes triggers OOB reads.
// Valid packed entry bytes from crate tests (32 bytes).
let entry_bytes: [u8; 32] = [
98, 121, 192, 21, 24, 76, 241, 100, 100, 106, 0, 4, 8, 48, 2, 17,
17, 145, 19, 117, 247, 0, 0, 0, 61, 232, 0, 253, 0, 39, 0, 2,
];
// num_plies = 1, but movetext is empty (chunk size == 32 + 2).
let mut chunk = Vec::new();
chunk.extend_from_slice(&entry_bytes);
chunk.extend_from_slice(&1u16.to_be_bytes());
// File header: "BINP" + chunk_size (LE).
let mut file = Vec::new();
file.extend_from_slice(b"BINP");
file.extend_from_slice(&(chunk.len() as u32).to_le_bytes());
file.extend_from_slice(&chunk);
let cursor = Cursor::new(file);
let mut reader = CompressedTrainingDataEntryReader::new(cursor).unwrap();
// First next() returns the stem entry and sets movelist_reader.
let _ = reader.next();
// Second next() consumes movetext via BitReader and triggers OOB.
let _ = reader.next();
}
error: Undefined Behavior: attempting a read access using <6505> at alloc788[0x22], but that tag does not exist in the borrow stack for this location
--> /Users/yxz/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/sfbinpack-0.6.1/src/reader/bitreader.rs:30:20
|
30 | byte = *self.movetext.add(self.read_offset) << (8 - self.read_bits_left);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this error occurs as part of an access at alloc788[0x22..0x23]
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
Hello, thank you for this crate! I've discovered a potential unsoundness that could trigger an Undefined Behavior (OOB) in secure code.
miri outputs: