Enet4/faiss-rs
Unsoundness: `RangeSearchResult` can have multiple owners, leading to a use-after-free/double-free
Open
#107 opened on Feb 10, 2026
bughelp wanted
Repository metrics
- Stars
- (252 stars)
- PR merge metrics
- (PR metrics pending)
Description
Hi,
following safe Rust snippet causes a use-after-free (or double-free if you remove the second println!):
use faiss::{Index, MetricType, index_factory};
fn main() -> anyhow::Result<()> {
let outer;
{
let mut index = index_factory(8, "Flat", MetricType::L2).unwrap();
let some_data = &[
7.5_f32, -7.5, 7.5, -7.5, 7.5, 7.5, 7.5, 7.5, -1., 1., 1., 1., 1., 1., 1., -1., 0., 0.,
0., 1., 1., 0., 0., -1., 100., 100., 100., 100., -100., 100., 100., 100., 120., 100.,
100., 105., -100., 100., 100., 105.,
];
index.add(some_data).unwrap();
let my_query = [0.; 8];
let result = index.range_search(&my_query, 8.125).unwrap();
println!("result: {:?}", result.distances());
outer = result.clone();
}
println!("result: {:?}", outer.distances());
Ok(())
}
$ RUSTFLAGS="-Zsanitizer=address" cargo r --release --target x86_64-unknown-linux-gnu
result: [8.0, 3.0]
=================================================================
==3021882==ERROR: AddressSanitizer: heap-use-after-free on address 0x7b6eb53e4278 at pc 0x5642d3eda099 bp 0x7ffe57a81670 sp 0x7ffe57a81668
The root cause is that #[derive(Clone)] on RangeSearchResult is not safe. Basically, on the clone the pointer itself gets duplicated but not the object. The RangeSearchResult, which goes out of scope first, will free the underlying object and cause UAFs/DFs on all others. Possible fixes are:
- Retrofit refcounting in Rust on FaissRangeSearchResult.
- Deep-copy the object in a custom
Cloneimplementation - Just remove
#[derive(Clone)]
Kind Regards Tim