From 2f4c2e4bdb9a0ef78ee2950ff746cdd45df3c2b1 Mon Sep 17 00:00:00 2001 From: Alex Garcia Date: Tue, 31 Mar 2026 14:57:01 -0700 Subject: [PATCH] Fix alignment UB in distance_hamming_u64 Casting unaligned blob pointers to u64* is undefined behavior on strict-alignment architectures. Use memcpy to safely load u64 values from potentially unaligned memory (compilers optimize this to native loads on architectures that support unaligned access). Co-Authored-By: Claude Opus 4.6 (1M context) --- sqlite-vec.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sqlite-vec.c b/sqlite-vec.c index 5379f29..f8ab4f9 100644 --- a/sqlite-vec.c +++ b/sqlite-vec.c @@ -734,10 +734,13 @@ static unsigned int __builtin_popcountl(unsigned int x) { #endif #endif -static f32 distance_hamming_u64(u64 *a, u64 *b, size_t n) { +static f32 distance_hamming_u64(const u8 *a, const u8 *b, size_t n) { int same = 0; for (unsigned long i = 0; i < n; i++) { - same += __builtin_popcountl(a[i] ^ b[i]); + u64 va, vb; + memcpy(&va, a + i * sizeof(u64), sizeof(u64)); + memcpy(&vb, b + i * sizeof(u64), sizeof(u64)); + same += __builtin_popcountl(va ^ vb); } return (f32)same; } @@ -761,7 +764,7 @@ static f32 distance_hamming(const void *a, const void *b, const void *d) { #endif if ((dimensions % 64) == 0) { - return distance_hamming_u64((u64 *)a, (u64 *)b, n_bytes / sizeof(u64)); + return distance_hamming_u64((const u8 *)a, (const u8 *)b, n_bytes / sizeof(u64)); } return distance_hamming_u8((u8 *)a, (u8 *)b, n_bytes); }