From d43336302e06aec21bd0822ef0cbb01c8c34d6be Mon Sep 17 00:00:00 2001 From: Michael Norris Date: Fri, 17 Jul 2026 10:16:31 -0700 Subject: [PATCH] Validate SVS-Vamana stored_vectors size on deserialization (ISV2) (#5434) Summary: Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5434 The `ISV2` (IndexSVSVamana) deserialization branch reads `ntotal`, `d` (header), and the raw `stored_vectors` payload as independent fields and never re-establishes the invariant `stored_vectors.size() == ntotal * d` that the programmatic `add()` path maintains. `IndexSVSVamana::reconstruct` guards only `key < ntotal` and `stored_vectors` non-empty, then `memcpy`s `sizeof(float) * d` bytes from `stored_vectors.data() + key * d`. A crafted index declaring e.g. `ntotal=1, d=256` with a 1-element payload reads ~1 KiB past the heap allocation (heap-buffer-overflow read). Adds the `stored_vectors.size() == ntotal * d` check at deserialization, matching the sibling flat-codes readers, converting the OOB read into a clean FaissException. The SVS family is compile-gated (FAISS_ENABLE_SVS, x86_64). Found by agentic fuzzing. Reviewed By: trang-nm-nguyen Differential Revision: D112368334 fbshipit-source-id: ba4ba275dd0444216139921c8d15628ccbb29fc0 --- faiss/impl/index_read.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/faiss/impl/index_read.cpp b/faiss/impl/index_read.cpp index 05a82a809..7d73af4c4 100644 --- a/faiss/impl/index_read.cpp +++ b/faiss/impl/index_read.cpp @@ -2851,6 +2851,13 @@ std::unique_ptr read_index_up(IOReader* f, int io_flags) { } if (h == fourcc("ISV2")) { READVECTOR(svs->stored_vectors); + FAISS_THROW_IF_NOT_MSG( + svs->stored_vectors.size() == + mul_no_overflow( + (size_t)svs->ntotal, + (size_t)svs->d, + "IndexSVSVamana stored_vectors"), + "ISV2: stored_vectors size inconsistent with ntotal * d"); } else { svs->stored_vectors_valid = false; }