@@ -439,3 +439,54 @@ TEST(ReadIndexDeserialize, BinaryHashEmptyInvlistBuffer) {
439439
440440 expect_binary_read_throws_with (buf, " binary hash invlists" );
441441}
442+
443+ // -----------------------------------------------------------------------
444+ // Test: IndexBinaryHash with b=0 triggers the b > 0 validation.
445+ // Without this check, BitstringReader::read(0) would silently produce
446+ // garbage hash values on every inverted-list entry.
447+ // -----------------------------------------------------------------------
448+ TEST (ReadIndexDeserialize, BinaryHashBZero) {
449+ std::vector<uint8_t > buf;
450+ push_fourcc (buf, " IBHh" );
451+ push_binary_index_header (buf, /* d=*/ 16 , /* ntotal=*/ 0 );
452+ push_val<int >(buf, 0 ); // b = 0 (invalid)
453+
454+ expect_binary_read_throws_with (buf, " IndexBinaryHash b=" );
455+ }
456+
457+ // -----------------------------------------------------------------------
458+ // Test: read_binary_hash_invlists with negative il_nbit triggers the
459+ // il_nbit >= 0 validation. Without this check, the negative value would
460+ // wrap to a huge size_t in the bits-per-entry calculation, causing an
461+ // out-of-bounds read in BitstringReader.
462+ // -----------------------------------------------------------------------
463+ TEST (ReadIndexDeserialize, BinaryHashNegativeIlNbit) {
464+ std::vector<uint8_t > buf;
465+ push_fourcc (buf, " IBHh" );
466+ push_binary_index_header (buf, /* d=*/ 16 , /* ntotal=*/ 0 );
467+ push_val<int >(buf, 4 ); // b
468+ push_val<int >(buf, 0 ); // nflip
469+ // read_binary_hash_invlists fields:
470+ push_val<size_t >(buf, size_t (0 )); // sz = 0
471+ push_val<int >(buf, -1 ); // il_nbit = -1 (invalid)
472+
473+ expect_binary_read_throws_with (buf, " il_nbit=" );
474+ }
475+
476+ // -----------------------------------------------------------------------
477+ // Test: read_binary_hash_invlists with il_nbit=0 but sz > 0 triggers
478+ // the il_nbit > 0 validation. Without this check, every inverted-list
479+ // size would silently read as 0, corrupting the deserialized index.
480+ // -----------------------------------------------------------------------
481+ TEST (ReadIndexDeserialize, BinaryHashIlNbitZeroWithEntries) {
482+ std::vector<uint8_t > buf;
483+ push_fourcc (buf, " IBHh" );
484+ push_binary_index_header (buf, /* d=*/ 16 , /* ntotal=*/ 0 );
485+ push_val<int >(buf, 4 ); // b
486+ push_val<int >(buf, 0 ); // nflip
487+ // read_binary_hash_invlists fields:
488+ push_val<size_t >(buf, size_t (1 )); // sz = 1 (non-zero)
489+ push_val<int >(buf, 0 ); // il_nbit = 0 (invalid when sz > 0)
490+
491+ expect_binary_read_throws_with (buf, " il_nbit=" );
492+ }
0 commit comments