Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions data/src/tensor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,15 @@ impl Tensor {
align: usize,
) -> TractResult<Tensor> {
let mut tensor = unsafe { Tensor::uninitialized_aligned_dt(dt, shape, align) }?;
let expected = tensor.as_bytes().len();
ensure!(
content.len() == expected,
"Raw tensor data length ({}) does not match shape {:?} of {:?} ({} bytes)",
content.len(),
shape,
dt,
expected
);
tensor.as_bytes_mut().copy_from_slice(content);
Ok(tensor)
}
Expand Down Expand Up @@ -1849,6 +1858,20 @@ mod tests {
use proptest::collection::vec;
use proptest::prelude::*;

// Regression for sonos/tract#2390: from_raw must reject a content length that
// does not match the declared shape rather than panicking in copy_from_slice.
#[test]
fn from_raw_rejects_length_mismatch() {
// shape [2, 3] of f32 needs 24 bytes; supply 12.
let err = unsafe { Tensor::from_raw_dt(f32::datum_type(), &[2, 3], &[0u8; 12]) }
.expect_err("from_raw must reject a short content buffer, not panic");
assert!(err.to_string().contains("does not match shape"), "unexpected error: {err}");
// Too-long content is rejected as well.
assert!(unsafe { Tensor::from_raw_dt(f32::datum_type(), &[2, 3], &[0u8; 32]) }.is_err());
// Exact match still succeeds.
assert!(unsafe { Tensor::from_raw_dt(f32::datum_type(), &[2, 3], &[0u8; 24]) }.is_ok());
}

#[derive(Debug)]
struct PermuteAxisProblem {
shape: Vec<usize>,
Expand Down