media/file: clamp firmware-reported read length in read_chunked

`read_chunked` trusted the byte count reported by the read callback. A
firmware reporting more than the requested size made `remaining_size`
underflow and advanced `output_ptr` past the end of the caller buffer,
causing out-of-bounds writes on the following chunk.

Clamp the reported length to the requested size.
This commit is contained in:
Philipp Schuster 2026-08-24 15:16:08 +02:00
parent e06b2e8330
commit b17551c70e
No known key found for this signature in database

View file

@ -177,6 +177,10 @@ where
let status = read(output_ptr, &mut read_size);
if status.is_success() {
// Never trust a firmware-reported length larger than what we
// requested; otherwise the pointer/size arithmetic below would
// run out of bounds.
let read_size = read_size.min(requested_read_size);
total_read_size += read_size;
remaining_size -= read_size;
// SAFETY: The memory is valid.
@ -282,4 +286,18 @@ mod tests {
assert_eq!(read_chunked(&mut buffer, 10, read), Ok(0));
assert_eq!(buffer, [0; 10]);
}
// Regression test: a callback (i.e. firmware) reporting a read length
// larger than requested must not cause `remaining_size` to underflow or
// `output_ptr` to walk out of bounds. The over-reported length is clamped.
#[test]
fn test_file_read_chunked_over_report() {
// A misbehaving read that always reports 2 bytes more than requested.
let read = |_buf: *mut u8, buf_size: &mut usize| {
*buf_size += 2;
Status::SUCCESS
};
let mut buffer = [0u8; 8];
assert_eq!(read_chunked(&mut buffer, 4, read), Ok(8));
}
}