From 0d264c6c57f086f4ca54d649691f24073dfe6647 Mon Sep 17 00:00:00 2001 From: Aleksey Shakhmatov Date: Sun, 2 Aug 2026 12:41:28 +0300 Subject: [PATCH] index: guard the $in cartesian cap against u64 overflow; drop debug print --- src/commands.zig | 1 - src/index.zig | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/commands.zig b/src/commands.zig index 505292c..ed2ea8f 100644 --- a/src/commands.zig +++ b/src/commands.zig @@ -1889,7 +1889,6 @@ test "indexed queries are equivalent to scans over a mixed corpus" { clear_id_list(testing.allocator, &scanned); try dispatch_find_ids(&tdb, io, "eq", f.pairs, &scanned); const indexed = indexed_results.items[fi]; - if (scanned.items.len != indexed.items.len) std.debug.print("MISMATCH(ab) filter {d}: scan={d} idx={d}\n", .{ fi, scanned.items.len, indexed.items.len }); try testing.expectEqual(scanned.items.len, indexed.items.len); for (scanned.items, indexed.items) |a, b| try testing.expectEqualSlices(u8, a, b); } diff --git a/src/index.zig b/src/index.zig index c086c27..b3c6128 100644 --- a/src/index.zig +++ b/src/index.zig @@ -706,6 +706,9 @@ fn evaluate_index(gpa: std.mem.Allocator, ix: *const Index, clauses: []const Cla } var combos: u64 = 1; for (0..run) |i| { + // A single huge $in list (or a product over 100) falls back to a + // scan; checking the factor first keeps the product from wrapping. + if (counts[i] > max_combos) return null; combos *= counts[i]; if (combos > max_combos) return null; }