Skip to content

[BUG] Rust: ManagedTensor borrows host ndarray shape storage; index outliving the host array reads a dangling pointer at Drop #2232

Description

@jamie8johnson

Describe the bug

In the Rust crate, ManagedTensor::from(&ndarray) stores arr.shape().as_ptr() — a pointer into the host ndarray's owned dimension storage — and .to_device() copies the DLTensor struct including that borrowed shape pointer. Index types that retain a non-owning device view of their build dataset (observed with brute_force::Index, which keeps _dataset) therefore alias the host array's dims. If the host Array2 is dropped (or moved out of scope) while the index is alive, the index's Drop reads the dangling shape pointer — observed as SIGABRT via multiply-overflow in dlpack.rs::dl_tensor_bytes.

Steps/Code to reproduce bug

let index = {
    let dataset: ndarray::Array2<f32> = /* ... */;
    let dev = ManagedTensor::from(&dataset).to_device(&res)?;
    brute_force::Index::build(&res, &params, &dev)?
    // dataset dropped here; index._dataset.shape now dangles
};
// index.drop() -> dl_tensor_bytes reads garbage dims -> SIGABRT

Nothing in the type system prevents this; it compiles cleanly.

Expected behavior

Either the borrow is impossible to outlive, or the tensor owns its shape.

Recommended fix

Make ManagedTensor own its shape/strides storage: copy the dims into an internal Box<[i64]> at construction and point DLTensor.shape at that owned buffer (likewise strides). This is API-compatible, costs a few words per tensor, and removes the hazard for every index type at once. The stricter alternative — threading a lifetime parameter (ManagedTensor<'a> with PhantomData<&'a ()>) — is sound but viral across every index API signature, so the owned-shape approach seems the better fit. We hit this while adding serialize bindings (#2231) and worked around it test-side with drop ordering; happy to submit the owned-shape fix as a PR if the approach sounds right.

Environment details

Rust crate at main (78135be), conda libcuvs 26.06, CUDA 13.1, RTX 4000.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status
    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions