mirror of
https://github.com/facebookresearch/faiss.git
synced 2026-10-12 02:13:36 +00:00
Add invlists null check to IndexBinaryIVF::search (#4980)
Summary: Pull Request resolved: https://github.com/facebookresearch/faiss/pull/4980 IndexBinaryIVF::search dereferences invlists via invlists->prefetch_lists() without any prior null check. The invlists pointer can legitimately be nullptr through multiple paths: 1. Default construction: IndexBinaryIVF::invlists is initialized to nullptr (IndexBinaryIVF.h:35) and the default constructor is defaulted, leaving it null. 2. Deserialization with IO_FLAG_SKIP_IVF_DATA: When this flag is set, read_InvertedLists_up returns nullptr, and the binary IVF reader at index_read.cpp:2130 stores it directly (ils.release() on a null unique_ptr yields nullptr). This is intentional — the flag allows loading index metadata without the (potentially large) inverted list data. 3. Deserialization with fourcc "il00": The serialized data explicitly indicates inverted lists were not stored with the IVF object (index_read.cpp:453), returning nullptr. Without this check, any of these cases would segfault on the invlists->prefetch_lists() call. With this check, the caller receives a clear FaissException explaining the misconfiguration. This mirrors the existing null check in the float IndexIVF::search (IndexIVF.cpp:312) which already guards against the same condition. Reviewed By: mnorris11 Differential Revision: D97848088 fbshipit-source-id: 406abb870dfa093ffc3ce49ba65904bebe4763a2
This commit is contained in:
committed by
meta-codesync[bot]
parent
ba1981ca4c
commit
b9f49601d1
@@ -124,6 +124,7 @@ void IndexBinaryIVF::search(
|
||||
idx_t* labels,
|
||||
const SearchParameters* params_in) const {
|
||||
FAISS_THROW_IF_NOT(k > 0);
|
||||
FAISS_THROW_IF_NOT_MSG(invlists, "IVF index has no inverted lists");
|
||||
const IVFSearchParameters* params = nullptr;
|
||||
if (params_in) {
|
||||
params = dynamic_cast<const IVFSearchParameters*>(params_in);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <faiss/Index.h>
|
||||
#include <faiss/IndexBinary.h>
|
||||
#include <faiss/IndexBinaryHNSW.h>
|
||||
#include <faiss/IndexBinaryIVF.h>
|
||||
#include <faiss/IndexFlat.h>
|
||||
#include <faiss/IndexHNSW.h>
|
||||
#include <faiss/IndexIVFFlat.h>
|
||||
@@ -1924,3 +1925,33 @@ TEST(ReadIndexDeserialize, BinaryHNSWCagraZeroEntrypoints) {
|
||||
},
|
||||
faiss::FaissException);
|
||||
}
|
||||
|
||||
// ---- IndexBinaryIVF runtime safety checks ----
|
||||
|
||||
TEST(ReadIndexDeserialize, BinaryIVFNullInvlistsSearch) {
|
||||
IndexBinaryIVF idx;
|
||||
idx.d = 16;
|
||||
idx.code_size = 2;
|
||||
idx.invlists = nullptr;
|
||||
idx.own_invlists = false;
|
||||
std::vector<int32_t> distances(1);
|
||||
std::vector<idx_t> labels(1);
|
||||
std::vector<uint8_t> query(2);
|
||||
EXPECT_THROW(
|
||||
{
|
||||
try {
|
||||
idx.search(
|
||||
1,
|
||||
query.data(),
|
||||
1,
|
||||
distances.data(),
|
||||
labels.data());
|
||||
} catch (const faiss::FaissException& e) {
|
||||
EXPECT_NE(
|
||||
std::string(e.what()).find("inverted lists"),
|
||||
std::string::npos);
|
||||
throw;
|
||||
}
|
||||
},
|
||||
faiss::FaissException);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user