Skip to content

Additional hardening of index load path#4817

Closed
scsiguy wants to merge 1 commit intofacebookresearch:mainfrom
scsiguy:export-D93486058
Closed

Additional hardening of index load path#4817
scsiguy wants to merge 1 commit intofacebookresearch:mainfrom
scsiguy:export-D93486058

Conversation

@scsiguy
Copy link
Contributor

@scsiguy scsiguy commented Feb 19, 2026

Summary:
Address input validation gaps in the load path:

#: 1
FPE (divide-by-zero)
Location: ProductQuantizer::set_derived_values()
Root Cause: M=0 causes d % M to divide by zero
Fix: Validate M > 0 in read_ProductQuantizer and set_derived_values()
────────────────────────────────────────
#: 2
OOB vector access
Location: AdditiveQuantizer::set_derived_values()
Root Cause: nbits.size() != M causes access to nbits[i] beyond bounds
Fix: Validate nbits.size() == M in read_AdditiveQuantizer
────────────────────────────────────────
#: 3
OOB vector access
Location: ResidualQuantizer old format
Root Cause: Same as #2 but via read_ResidualQuantizer_old path
Fix: Validate nbits.size() == M in read_ResidualQuantizer_old
────────────────────────────────────────
#: 4
Integer overflow
Location: ProductQuantizer::set_derived_values()
Root Cause: d * ksub overflows when nbits is large
Fix: Use mul_no_overflow() for centroids.resize(), moved nbits > 24 check
before code_size computation
────────────────────────────────────────
#: 5
FPE (divide-by-zero) + stack overflow
Location: IndexLattice constructor
Root Cause: nsq=0 causes d/nsq divide-by-zero; garbage nsq causes stack
overflow in ZnSphereCodec
Fix: Validate nsq > 0, d > 0, d % nsq == 0, r2 >= 0 before construction
Files Modified

Reviewed By: mdouze

Differential Revision: D93486058

Summary:
Address input validation gaps in the load path:

#: 1
FPE (divide-by-zero)
Location: ProductQuantizer::set_derived_values()
Root Cause: M=0 causes d % M to divide by zero
Fix: Validate M > 0 in read_ProductQuantizer and set_derived_values()
────────────────────────────────────────
#: 2
OOB vector access
Location: AdditiveQuantizer::set_derived_values()
Root Cause: nbits.size() != M causes access to nbits[i] beyond bounds
Fix: Validate nbits.size() == M in read_AdditiveQuantizer
────────────────────────────────────────
#: 3
OOB vector access
Location: ResidualQuantizer old format
Root Cause: Same as facebookresearch#2 but via read_ResidualQuantizer_old path
Fix: Validate nbits.size() == M in read_ResidualQuantizer_old
────────────────────────────────────────
#: 4
Integer overflow
Location: ProductQuantizer::set_derived_values()
Root Cause: d * ksub overflows when nbits is large
Fix: Use mul_no_overflow() for centroids.resize(), moved nbits > 24 check
before code_size computation
────────────────────────────────────────
#: 5
FPE (divide-by-zero) + stack overflow
Location: IndexLattice constructor
Root Cause: nsq=0 causes d/nsq divide-by-zero; garbage nsq causes stack
overflow in ZnSphereCodec
Fix: Validate nsq > 0, d > 0, d % nsq == 0, r2 >= 0 before construction
Files Modified

Reviewed By: mdouze

Differential Revision: D93486058
@meta-codesync
Copy link
Contributor

meta-codesync bot commented Feb 19, 2026

@scsiguy has exported this pull request. If you are a Meta employee, you can view the originating Diff in D93486058.

@meta-cla meta-cla bot added the CLA Signed label Feb 19, 2026
scsiguy added a commit to scsiguy/faiss that referenced this pull request Feb 19, 2026
Summary:

Address input validation gaps in the load path:

#: 1
FPE (divide-by-zero)
Location: ProductQuantizer::set_derived_values()
Root Cause: M=0 causes d % M to divide by zero
Fix: Validate M > 0 in read_ProductQuantizer and set_derived_values()
────────────────────────────────────────
#: 2
OOB vector access
Location: AdditiveQuantizer::set_derived_values()
Root Cause: nbits.size() != M causes access to nbits[i] beyond bounds
Fix: Validate nbits.size() == M in read_AdditiveQuantizer
────────────────────────────────────────
#: 3
OOB vector access
Location: ResidualQuantizer old format
Root Cause: Same as facebookresearch#2 but via read_ResidualQuantizer_old path
Fix: Validate nbits.size() == M in read_ResidualQuantizer_old
────────────────────────────────────────
#: 4
Integer overflow
Location: ProductQuantizer::set_derived_values()
Root Cause: d * ksub overflows when nbits is large
Fix: Use mul_no_overflow() for centroids.resize(), moved nbits > 24 check
before code_size computation
────────────────────────────────────────
#: 5
FPE (divide-by-zero) + stack overflow
Location: IndexLattice constructor
Root Cause: nsq=0 causes d/nsq divide-by-zero; garbage nsq causes stack
overflow in ZnSphereCodec
Fix: Validate nsq > 0, d > 0, d % nsq == 0, r2 >= 0 before construction
Files Modified

Reviewed By: mdouze

Differential Revision: D93486058
@meta-codesync meta-codesync bot closed this in d260887 Feb 20, 2026
@meta-codesync
Copy link
Contributor

meta-codesync bot commented Feb 20, 2026

This pull request has been merged in d260887.

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