Fix remaining fuzzer issues: leaks, UBSAN NaN, macOS LLVM version

- fuzz.yaml: switch macOS to llvm@18 (latest LLVM uses typed allocation
  C++ ABI symbols not available on macOS 14 runner's system libc++)
- sqlite-vec.c: fix NaN input in vec_quantize_int8 by using !(val <= X)
  comparisons which evaluate to true for NaN, ensuring the clamp fires
- sqlite-vec.c: free pzErrMsg in vec_eachFilter error path (was leaking
  the error string returned by vector_from_value)
- sqlite-vec.c: add sqlite3_free(pNew) to vec0_init error path; vec0_free
  frees the contents but not the struct itself, mirroring vec0Disconnect
- sqlite-vec.c: free knn_data in vec0Filter_knn cleanup when rc != SQLITE_OK;
  on error the cursor's knn_data field is never set so it would not be
  freed by the cursor teardown path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Alex Garcia 2026-03-03 08:36:59 -08:00
parent 8c976205dd
commit 1b53b942e0
2 changed files with 13 additions and 7 deletions

View file

@ -1465,8 +1465,8 @@ static void vec_quantize_int8(sqlite3_context *context, int argc,
f32 step = (1.0 - (-1.0)) / 255;
for (size_t i = 0; i < dimensions; i++) {
double val = ((srcVector[i] - (-1.0)) / step) - 128;
if (val > 127.0) val = 127.0;
if (val < -128.0) val = -128.0;
if (!(val <= 127.0)) val = 127.0; /* also clamps NaN */
if (!(val >= -128.0)) val = -128.0;
out[i] = (i8)val;
}
@ -2577,6 +2577,7 @@ static int vec_eachFilter(sqlite3_vtab_cursor *pVtabCursor, int idxNum,
int rc = vector_from_value(argv[0], &pCur->vector, &pCur->dimensions,
&pCur->vector_type, &pCur->cleanup, &pzErrMsg);
if (rc != SQLITE_OK) {
sqlite3_free(pzErrMsg);
return SQLITE_ERROR;
}
pCur->iRowid = 0;
@ -5202,6 +5203,7 @@ static int vec0_init(sqlite3 *db, void *pAux, int argc, const char *const *argv,
error:
vec0_free(pNew);
sqlite3_free(pNew);
return SQLITE_ERROR;
}
@ -7259,6 +7261,10 @@ cleanup:
sqlite3_free(aMetadataIn);
if (rc != SQLITE_OK) {
sqlite3_free(knn_data);
}
return rc;
}