Reject null base/refine index in IndexRefine deserialization (#5466)

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

Agentic fuzzing (T279899090) found a null-pointer dereference reachable
through `faiss::read_index`. The serialized-index format uses a `"null"`
fourcc to denote a missing sub-index, for which `read_index_up` returns an
empty pointer. The `IxRF`/`IxRP` (`IndexRefine`) branch assigned both
nested `read_index_up` results to `base_index`/`refine_index` without a
null check, so a crafted stream with `"null"` sub-indexes deserialized
into an `IndexRefine` whose pointers are null. The first `reconstruct()`
(or any other method) then dispatched a virtual call through the null
`refine_index`, crashing with a near-null SIGSEGV.

Add `FAISS_THROW_IF_NOT_MSG` guards for both sub-indexes, matching the
adjacent `IxMp`/`IxM2` (`IndexIDMap`) branch which already rejects a null
inner index. The malformed stream now raises a catchable `FaissException`.

Reviewed By: trang-nm-nguyen

Differential Revision: D113119810

fbshipit-source-id: 59e812d4252478a35b9d9f823fa371bd0dcfff54
This commit is contained in:
Michael Norris
2026-07-24 09:30:29 -07:00
committed by meta-codesync[bot]
parent d4564bdeb2
commit 6a0616edbd
+2
View File
@@ -2333,6 +2333,8 @@ std::unique_ptr<Index> read_index_up(IOReader* f, int io_flags) {
read_index_header(*idxrf, f);
auto base = read_index_up(f, io_flags);
auto refine = read_index_up(f, io_flags);
FAISS_THROW_IF_NOT_MSG(base, "IndexRefine base index is null");
FAISS_THROW_IF_NOT_MSG(refine, "IndexRefine refine index is null");
READ1(idxrf->k_factor);
// Same rationale as IndexIVFPQR k_factor above.
FAISS_THROW_IF_NOT_FMT(