Enet4/faiss-rs

Unsoundness: `RangeSearchResult` can have multiple owners, leading to a use-after-free/double-free

Open

#107 opened on Feb 10, 2026

 (1 comment) (1 reaction) (0 assignees)Rust (50 forks)auto 404
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:

  1. Retrofit refcounting in Rust on FaissRangeSearchResult.
  2. Deep-copy the object in a custom Clone implementation
  3. Just remove #[derive(Clone)]

Kind Regards Tim

Contributor guide