Skip to content

Validate codebook size in read_ResidualQuantizer_old and bounds-check IndexBinaryIVF::reconstruct_from_offset - #5764

Open
professor-moody wants to merge 1 commit into
facebookresearch:mainfrom
professor-moody:fix/rq-old-codebooks-and-binary-ivf-bounds
Open

professor-moody wants to merge 1 commit into
facebookresearch:mainfrom
professor-moody:fix/rq-old-codebooks-and-binary-ivf-bounds

Conversation

@professor-moody

@professor-moody professor-moody commented Oct 21, 2026 •

Copy link
Copy Markdown

Summary

This change extends existing deserialization and reconstruction bounds checks to two remaining sibling code paths:

  1. read_ResidualQuantizer_old and "IxRQ" / "IxRq" reader (faiss/impl/index_read.cpp):

    • read_ResidualQuantizer, read_LocalSearchQuantizer, and read_ProductAdditiveQuantizer call validate_codebooks_size(const AdditiveQuantizer& aq, size_t effective_d) so that additive quantizers with a truncated codebooks buffer are rejected during read_index().
    • The legacy reader read_ResidualQuantizer_old (used by the "IxRQ" fourcc branch) sits above validate_codebooks_size in faiss/impl/index_read.cpp and did not call it after rq.set_derived_values(). Forward-declaring validate_codebooks_size and calling validate_codebooks_size(rq, rq.d) at the end of read_ResidualQuantizer_old (allowing an early return only when !aq.is_trained && aq.codebooks.empty()) ensures legacy residual quantizer streams enforce codebooks.size() >= d * total_codebook_size before AdditiveQuantizer::decode or compute_codes indexes codebooks.
    • Additionally, in the "IxRQ" / "IxRq" IndexResidualQuantizer reader block, enforce idxr->rq.is_trained == idxr->is_trained and idxr->ntotal == 0 || idxr->rq.is_trained so a stream cannot mark the outer index trained (or populate ntotal > 0 codes) while leaving the inner ResidualQuantizer untrained with empty codebooks.
  2. IndexBinaryIVF::reconstruct_from_offset (faiss/IndexBinaryIVF.cpp):

    • Float IndexIVF::reconstruct validates list_no and offset at runtime because DirectMap::get(key) does not validate the decoded (list_no, offset) pair stored in a serialized direct_map and assertions inside ArrayInvertedLists are compiled out under NDEBUG.
    • Adding runtime FAISS_THROW_IF_NOT_FMT checks on list_no >= 0 && static_cast<uint64_t>(list_no) < static_cast<uint64_t>(nlist) and offset >= 0 && static_cast<uint64_t>(offset) < static_cast<uint64_t>(invlists->list_size(list_no)) in IndexBinaryIVF::reconstruct_from_offset protects both IndexBinaryIVF::reconstruct(key, recons) and IndexBinaryIVF::search_and_reconstruct without 32-bit size_t truncation.

Test Plan

  • Verified with regression tests covering:
    • Legacy "IxRQ" deserialization with valid codebooks (control), truncated codebooks with rq.is_trained = true (mode_rq_old), and inconsistent outer idxr->is_trained = true, ntotal = 1 with inner rq.is_trained = false (mode_rq_old_untrained_mismatch).
    • Binary IVF ("IBIv") reconstruction with valid DirectMap::Array entries (control) and out-of-bounds (list_no, offset) entries (offset >= list_size(list_no) and list_no >= nlist).
  • Confirmed clean pass under both Release (-O3 -DNDEBUG) and ASan+UBSan (-fsanitize=address,undefined -g -O1).

Note: This patch was prepared with AI assistance and verified by human review and local test execution.

@meta-cla

meta-cla Bot commented Oct 21, 2026

Copy link
Copy Markdown

Hi @professor-moody!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

@meta-codesync

meta-codesync Bot commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

@trang-nm-nguyen has imported this pull request. If you are a Meta employee, you can view this in D126706046.

@meta-cla

meta-cla Bot commented Oct 21, 2026

Copy link
Copy Markdown

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

@meta-cla meta-cla Bot added the CLA Signed label Oct 21, 2026

@ability-spec ability-spec left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants