mirror of
https://github.com/facebookresearch/faiss.git
synced 2026-10-11 22:50:00 +00:00
Validate Panorama batch_size and codes/cum_sums on deserialization (#5438)
Summary: Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5438 The `IndexFlatPanorama` (`IxFP`/`IxFp`) and `IndexIVFFlatPanorama` (`IwP2`) deserialization branches read fields that are trusted as invariants at reconstruct time but are never validated: - `batch_size` is read straight from the stream and used as a divisor in `Panorama::reconstruct` (`key / batch_size`, `key % batch_size`). A crafted index with `batch_size == 0` raises SIGFPE. The sibling `ilp2` branch already guards this exact field; the IxFP/IxFp and IwP2 branches did not. - `codes`/`cum_sums` are read independently of `ntotal`, so a forged `ntotal > 0` with an empty (or undersized) `codes`/`cum_sums` vector passes deserialization and then reads through a null/out-of-bounds pointer in `Panorama::reconstruct`'s `memcpy`. Every non-Panorama flat reader already enforces the analogous size invariant. Adds a `batch_size > 0` guard (both branches) and a codes/cum_sums size check that mirrors the whole-batch padding layout in `IndexFlatPanorama::add`. Converts the crashes into clean FaissExceptions. Found by agentic fuzzing. Reviewed By: trang-nm-nguyen Differential Revision: D112368332 fbshipit-source-id: 76bb667bc69a5ac048234fa0b4f51a924f1ae1c2
This commit is contained in:
committed by
meta-codesync[bot]
parent
d43336302e
commit
fba9084a62
@@ -1617,6 +1617,8 @@ std::unique_ptr<Index> read_index_up(IOReader* f, int io_flags) {
|
||||
READ1(n_levels);
|
||||
FAISS_THROW_IF_NOT_FMT(n_levels > 0, "invalid n_levels %zd", n_levels);
|
||||
READ1(batch_size);
|
||||
FAISS_THROW_IF_NOT_FMT(
|
||||
batch_size > 0, "invalid IxFP batch_size %zd", batch_size);
|
||||
std::unique_ptr<IndexFlatPanorama> idxp;
|
||||
if (h == fourcc("IxFP")) {
|
||||
idxp = std::make_unique<IndexFlatL2Panorama>(
|
||||
@@ -1629,6 +1631,21 @@ std::unique_ptr<Index> read_index_up(IOReader* f, int io_flags) {
|
||||
READ1_BOOL(idxp->is_trained);
|
||||
READVECTOR(idxp->codes);
|
||||
READVECTOR(idxp->cum_sums);
|
||||
size_t num_slots = mul_no_overflow(
|
||||
((size_t)idxp->ntotal + idxp->batch_size - 1) /
|
||||
idxp->batch_size,
|
||||
idxp->batch_size,
|
||||
"IndexFlatPanorama num_batches*batch_size");
|
||||
FAISS_THROW_IF_NOT(
|
||||
idxp->codes.size() ==
|
||||
mul_no_overflow(
|
||||
num_slots, idxp->code_size, "IndexFlatPanorama codes"));
|
||||
FAISS_THROW_IF_NOT(
|
||||
idxp->cum_sums.size() ==
|
||||
mul_no_overflow(
|
||||
num_slots,
|
||||
idxp->pano.n_levels + 1,
|
||||
"IndexFlatPanorama cum_sums"));
|
||||
idxp->verbose = false;
|
||||
idx = std::move(idxp);
|
||||
} else if (
|
||||
@@ -2044,6 +2061,10 @@ std::unique_ptr<Index> read_index_up(IOReader* f, int io_flags) {
|
||||
ivfp->code_size = ivfp->d * sizeof(float);
|
||||
READ1(ivfp->n_levels);
|
||||
READ1(ivfp->batch_size);
|
||||
FAISS_THROW_IF_NOT_FMT(
|
||||
ivfp->batch_size > 0,
|
||||
"invalid IwP2 batch_size %zd",
|
||||
ivfp->batch_size);
|
||||
read_InvertedLists(*ivfp, f, io_flags);
|
||||
idx = std::move(ivfp);
|
||||
} else if (h == fourcc("IwFl")) {
|
||||
|
||||
Reference in New Issue
Block a user