Fix IndexFastScan::reset() leaving stale ntotal2 (crash on search) (#5614)

Summary:
reset() cleared ntotal and the codes buffer but left ntotal2 (the bbs-padded scan count) unchanged. A search after reset then scans ntotal2/bbs blocks over the freed, empty code buffer, dereferencing a null pointer in the SIMD kernel and crashing with SIGSEGV (Fixes https://github.com/facebookresearch/faiss/issues/5591).

Clear ntotal2 in reset() too, matching init_fastscan(). This covers all flat FastScan indexes (PQ/AQ/RaBitQ), which share this reset().

Add test_reset reproducing train -> add -> reset -> search: it checks ntotal2 == 0 after reset and that searching the emptied index is safe and returns the -1 sentinel.

Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5614

Reviewed By: junjieqi

Differential Revision: D124253538

Pulled By: mnorris11

fbshipit-source-id: 038186130c03534fc353eae9390f031413a05a5e
This commit is contained in:
Eppalapelly Madhukar
2026-10-08 22:43:31 -07:00
committed by meta-codesync[bot]
parent 6692d7ab37
commit 8b884ecc96
2 changed files with 16 additions and 1 deletions
+1 -1
View File
@@ -55,7 +55,7 @@ IndexFastScan::IndexFastScan()
void IndexFastScan::reset() {
codes.resize(0);
ntotal = 0;
ntotal = ntotal2 = 0;
}
void IndexFastScan::add(idx_t n, const float* x) {
+15
View File
@@ -567,6 +567,21 @@ class TestAdd(unittest.TestCase):
np.testing.assert_array_equal(D3, Dnew)
np.testing.assert_array_equal(I3, Inew)
def test_reset(self):
d = 32
ds = datasets.SyntheticDataset(d, 2000, 5000, 200)
index = faiss.IndexPQFastScan(d, d // 2, 4)
index.train(ds.get_train())
index.add(ds.get_database())
index.reset()
self.assertEqual(index.ntotal, 0)
self.assertEqual(index.ntotal2, 0)
D, I = index.search(ds.get_queries(), 10)
np.testing.assert_array_equal(I, -1)
class TestAQFastScan(unittest.TestCase):