Skip to content

Commit 4bee883

Browse files
asg017claude
andcommitted
Reject IVF binary quantizer when dimensions not divisible by 8
The binary quantizer uses D/8 for buffer sizes and memset, which truncates for non-multiple-of-8 dimensions, causing OOB writes. Rather than using ceiling division, enforce the constraint at table creation time with a clear parse error. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 5e4c557 commit 4bee883

2 files changed

Lines changed: 20 additions & 0 deletions

File tree

‎sqlite-vec.c‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3074,6 +3074,9 @@ int vec0_parse_vector_column(const char *source, int source_length,
30743074
if (rc != SQLITE_OK) {
30753075
return SQLITE_ERROR;
30763076
}
3077+
if (ivfConfig.quantizer == VEC0_IVF_QUANTIZER_BINARY && (dimensions % 8) != 0) {
3078+
return SQLITE_ERROR;
3079+
}
30773080
#else
30783081
return SQLITE_ERROR; // IVF not compiled in
30793082
#endif

‎tests/test-ivf-quantization.py‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,3 +253,20 @@ def test_ivf_quantized_delete(db):
253253
db.execute("DELETE FROM t WHERE rowid = 5")
254254
# _ivf_vectors should have 9 rows
255255
assert db.execute("SELECT count(*) FROM t_ivf_vectors00").fetchone()[0] == 9
256+
257+
258+
def test_ivf_binary_rejects_non_multiple_of_8_dims(db):
259+
"""Binary quantizer requires dimensions divisible by 8."""
260+
with pytest.raises(sqlite3.OperationalError):
261+
db.execute(
262+
"CREATE VIRTUAL TABLE t USING vec0("
263+
" v float[12] indexed by ivf(quantizer=binary)"
264+
")"
265+
)
266+
267+
# Dimensions divisible by 8 should work
268+
db.execute(
269+
"CREATE VIRTUAL TABLE t2 USING vec0("
270+
" v float[16] indexed by ivf(quantizer=binary)"
271+
")"
272+
)

0 commit comments

Comments
 (0)