faiss: fix IndexIDMap range_search crash with empty SearchParameters (#5388)

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

IndexIDMap::range_search checked only if params is non-null, then
unconditionally constructed IDSelectorTranslated with params->sel.
When an empty SearchParameters() is passed, sel is nullptr, leading
to null dereference in IDSelectorTranslated::is_member -> crash/hang.

This mirrors the existing guard in search_ex which checks
params && params->sel. Update range_search to same logic and pass
through params when sel is null, so empty SearchParameters behaves
same as no params.

I also took a quick look at other search functions. They all use this pattern if they support IDSelector (some do not).

Fixes https://github.com/facebookresearch/faiss/issues/5332

Reviewed By: alibeklfc

Differential Revision: D110987904

fbshipit-source-id: 3d87625cfc733e9ff6c7352f13e167feceae8d76
This commit is contained in:
Michael Norris
2026-07-08 10:33:33 -07:00
committed by meta-codesync[bot]
parent e306f3036d
commit ed29dbb0bb
2 changed files with 28 additions and 2 deletions
+2 -2
View File
@@ -228,14 +228,14 @@ void IndexIDMapTemplate<IndexT>::range_search(
typename IndexT::distance_t radius,
RangeSearchResult* result,
const SearchParameters* params) const {
if (params) {
if (params && params->sel) {
SearchParameters internal_search_parameters;
IDSelectorTranslated id_selector_translated(id_map, params->sel);
internal_search_parameters.sel = &id_selector_translated;
index->range_search(n, x, radius, result, &internal_search_parameters);
} else {
index->range_search(n, x, radius, result);
index->range_search(n, x, radius, result, params);
}
const idx_t id_map_size = static_cast<idx_t>(id_map.size());
+26
View File
@@ -337,6 +337,32 @@ class TestSelector(unittest.TestCase):
np.testing.assert_array_equal(Iref, Inew)
np.testing.assert_array_almost_equal(Dref, Dnew, decimal=5)
def test_idmap_range_empty_params(self):
# This test crashes without checking both params && params->sel
# are non null in IndexIDMap::range_search().
index = faiss.IndexIDMap(faiss.IndexFlatL2(2))
xb = np.array(
[
[0, 0],
[1, 0],
[0, 2],
],
dtype="float32",
)
ids = np.array([10, 20, 30], dtype="int64")
index.add_with_ids(xb, ids)
xq = np.array([[0, 0]], dtype="float32")
lims_ref, D_ref, I_ref = index.range_search(xq, 5.0)
lims, D, I = index.range_search(
xq, 5.0, params=faiss.SearchParameters()
)
np.testing.assert_array_equal(lims_ref, lims)
np.testing.assert_array_equal(sorted(I_ref), sorted(I))
np.testing.assert_array_equal(sorted(D_ref), sorted(D))
def test_bounds(self):
# https://github.com/facebookresearch/faiss/issues/3156
d = 64 # dimension