Summary
strided-perm::copy_into (strided-perm/src/copy.rs:62) and copy_into_par (:113) both
take a contiguous fast path that calls std::ptr::copy_nonoverlapping without validating
that the source and destination memory ranges are non-overlapping. copy_nonoverlapping
is Undefined Behavior if src and dst overlap, and the overlapping case is reachable
from safe code: two views built over the same backing buffer via
StridedArray::from_parts (different offsets / strides / dims) can both satisfy
is_both_contiguous while their linear ranges intersect.
Location
strided-perm/src/copy.rs:80-84 — copy_into contiguous fast path
strided-perm/src/copy.rs:134-138 — copy_into_par contiguous fast path
- Both are public API re-exported from
strided-perm/src/lib.rs:26-28
// strided-perm/src/copy.rs:81-84
if is_both_contiguous(dst_dims, dst_strides, src_strides) {
let len = total_len(dst_dims);
unsafe { std::ptr::copy_nonoverlapping(src_ptr, dst_ptr, len) }; // NO overlap check
return Ok(());
}
is_both_contiguous (copy.rs:13) checks only that each view's strides are col-major or
row-major; it does not check whether the two views alias. The function validates rank and
shape but omits the aliasing precondition entirely.
Rule violated
REPOSITORY_RULES.md:37-39 (## Public Boundary Safety): "User-reachable
tensor/view/kernel APIs must validate rank, shape, dtype, stride/layout, output shape,
and aliasing preconditions before no-op shortcuts, allocation, launch planning, or
unsafe pointer loops."
REPOSITORY_RULES.md:51-52 (## Unsafe And Fast-Path Boundaries): "Keep unsafe
pointer arithmetic close to the validation that proves it safe, and cover new unsafe
branches with focused tests."
Sibling-crate contrast
The strided-kernel counterpart (strided-kernel/src/ops_view.rs:209-235) at least has a
debug_assert! overlap check before its copy_nonoverlapping fast path. strided-perm
has no check of any kind (not even debug-only), and the debug-only check in strided-kernel
compiles out in release builds anyway.
Reproducible
Yes. Build two StridedArray over the same buffer with overlapping contiguous views,
construct a StridedViewMut and a StridedView, and call strided_perm::copy_into
(which re-exports copy::copy_into) when is_both_contiguous returns true. The
copy_nonoverlapping call fires on overlapping memory -> UB.
Proposed fix shape
- Validate src/dst non-overlap (e.g. byte-range disjointness as in
strided-kernel/src/ops_view.rs:212-224) at the public boundary before the fast path;
return a crate error (or fall back to the blocked permutation path) on overlap.
- Keep the check in release builds, not only
debug_assert!.
- Add focused overlapping-view tests for both
copy_into and copy_into_par.
Optional repository rule revision
Consider making the audit rule explicit that debug-only aliasing checks are not
sufficient at a public boundary — the "validate aliasing preconditions before unsafe
pointer loops" rule in REPOSITORY_RULES.md should apply in release builds and should be
called out for every ptr::copy_nonoverlapping / raw-pointer fast path (notably the
strided-kernel copy_into fast path, whose check is debug-gated).
Summary
strided-perm::copy_into(strided-perm/src/copy.rs:62) andcopy_into_par(:113) bothtake a contiguous fast path that calls
std::ptr::copy_nonoverlappingwithout validatingthat the source and destination memory ranges are non-overlapping.
copy_nonoverlappingis Undefined Behavior if
srcanddstoverlap, and the overlapping case is reachablefrom safe code: two views built over the same backing buffer via
StridedArray::from_parts(different offsets / strides / dims) can both satisfyis_both_contiguouswhile their linear ranges intersect.Location
strided-perm/src/copy.rs:80-84—copy_intocontiguous fast pathstrided-perm/src/copy.rs:134-138—copy_into_parcontiguous fast pathstrided-perm/src/lib.rs:26-28is_both_contiguous(copy.rs:13) checks only that each view's strides are col-major orrow-major; it does not check whether the two views alias. The function validates rank and
shape but omits the aliasing precondition entirely.
Rule violated
REPOSITORY_RULES.md:37-39(## Public Boundary Safety): "User-reachabletensor/view/kernel APIs must validate rank, shape, dtype, stride/layout, output shape,
and aliasing preconditions before no-op shortcuts, allocation, launch planning, or
unsafe pointer loops."
REPOSITORY_RULES.md:51-52(## Unsafe And Fast-Path Boundaries): "Keep unsafepointer arithmetic close to the validation that proves it safe, and cover new unsafe
branches with focused tests."
Sibling-crate contrast
The
strided-kernelcounterpart (strided-kernel/src/ops_view.rs:209-235) at least has adebug_assert!overlap check before itscopy_nonoverlappingfast path.strided-permhas no check of any kind (not even debug-only), and the debug-only check in
strided-kernelcompiles out in release builds anyway.
Reproducible
Yes. Build two
StridedArrayover the same buffer with overlapping contiguous views,construct a
StridedViewMutand aStridedView, and callstrided_perm::copy_into(which re-exports
copy::copy_into) whenis_both_contiguousreturnstrue. Thecopy_nonoverlappingcall fires on overlapping memory -> UB.Proposed fix shape
strided-kernel/src/ops_view.rs:212-224) at the public boundary before the fast path;return a crate error (or fall back to the blocked permutation path) on overlap.
debug_assert!.copy_intoandcopy_into_par.Optional repository rule revision
Consider making the audit rule explicit that debug-only aliasing checks are not
sufficient at a public boundary — the "validate aliasing preconditions before unsafe
pointer loops" rule in
REPOSITORY_RULES.mdshould apply in release builds and should becalled out for every
ptr::copy_nonoverlapping/ raw-pointer fast path (notably thestrided-kernelcopy_intofast path, whose check is debug-gated).