From d04e2aeda1c986327c969fffec3655929e2adb4c Mon Sep 17 00:00:00 2001 From: Alex Garcia Date: Tue, 3 Mar 2026 17:35:41 -0800 Subject: [PATCH] Fix remaining fuzzer issues: leaks and macOS SDK headers sqlite-vec.c: - vec0_free: add loops to free partition, auxiliary, and metadata column names (previously leaked on error paths) - vec0_init: update pNew->numXxxColumns incrementally in the parse loop so vec0_free sees correct counts on early goto-error paths (previously the counts were only written after the loop, so vec0_free would loop 0 times and leak names allocated inside the loop) fuzz.yaml: - macOS: pass -isysroot $(xcrun --sdk macosx --show-sdk-path) so Xcode clang can find system headers (stdio.h, assert.h, etc.) - Fix artifact upload paths: libFuzzer writes crash-*/leak-* to the cwd (repo root), not tests/fuzz/ Co-Authored-By: Claude Opus 4.6 --- .github/workflows/fuzz.yaml | 15 ++++++++------- sqlite-vec.c | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/.github/workflows/fuzz.yaml b/.github/workflows/fuzz.yaml index d07cf7d..f058961 100644 --- a/.github/workflows/fuzz.yaml +++ b/.github/workflows/fuzz.yaml @@ -55,9 +55,9 @@ jobs: with: name: fuzz-crashes-linux path: | - tests/fuzz/crash-* - tests/fuzz/leak-* - tests/fuzz/timeout-* + crash-* + leak-* + timeout-* fuzz-macos: runs-on: macos-14 @@ -70,9 +70,10 @@ jobs: run: make sqlite-vec.h - name: Build fuzz targets run: | + SDK=$(xcrun --sdk macosx --show-sdk-path) make -C tests/fuzz all \ FUZZ_CC=$(xcrun -f clang) \ - FUZZ_LDFLAGS="" + FUZZ_LDFLAGS="-isysroot $SDK" - name: Run fuzz targets run: | DURATION=${{ github.event.inputs.duration || '60' }} @@ -100,9 +101,9 @@ jobs: with: name: fuzz-crashes-macos path: | - tests/fuzz/crash-* - tests/fuzz/leak-* - tests/fuzz/timeout-* + crash-* + leak-* + timeout-* fuzz-windows: # Best-effort: libFuzzer works on Windows via LLVM but ASAN/UBSAN diff --git a/sqlite-vec.c b/sqlite-vec.c index 45fbec9..a6cb851 100644 --- a/sqlite-vec.c +++ b/sqlite-vec.c @@ -3659,6 +3659,21 @@ void vec0_free(vec0_vtab *p) { sqlite3_free(p->vector_columns[i].name); p->vector_columns[i].name = NULL; } + + for (int i = 0; i < p->numPartitionColumns; i++) { + sqlite3_free(p->paritition_columns[i].name); + p->paritition_columns[i].name = NULL; + } + + for (int i = 0; i < p->numAuxiliaryColumns; i++) { + sqlite3_free(p->auxiliary_columns[i].name); + p->auxiliary_columns[i].name = NULL; + } + + for (int i = 0; i < p->numMetadataColumns; i++) { + sqlite3_free(p->metadata_columns[i].name); + p->metadata_columns[i].name = NULL; + } } int vec0_num_defined_user_columns(vec0_vtab *p) { @@ -4742,6 +4757,7 @@ static int vec0_init(sqlite3 *db, void *pAux, int argc, const char *const *argv, pNew->user_column_idxs[user_column_idx] = numVectorColumns; memcpy(&pNew->vector_columns[numVectorColumns], &vecColumn, sizeof(vecColumn)); numVectorColumns++; + pNew->numVectorColumns = numVectorColumns; user_column_idx++; continue; @@ -4770,6 +4786,7 @@ static int vec0_init(sqlite3 *db, void *pAux, int argc, const char *const *argv, pNew->user_column_idxs[user_column_idx] = numPartitionColumns; memcpy(&pNew->paritition_columns[numPartitionColumns], &partitionColumn, sizeof(partitionColumn)); numPartitionColumns++; + pNew->numPartitionColumns = numPartitionColumns; user_column_idx++; continue; } @@ -4815,6 +4832,7 @@ static int vec0_init(sqlite3 *db, void *pAux, int argc, const char *const *argv, pNew->user_column_idxs[user_column_idx] = numAuxiliaryColumns; memcpy(&pNew->auxiliary_columns[numAuxiliaryColumns], &auxColumn, sizeof(auxColumn)); numAuxiliaryColumns++; + pNew->numAuxiliaryColumns = numAuxiliaryColumns; user_column_idx++; continue; } @@ -4842,6 +4860,7 @@ static int vec0_init(sqlite3 *db, void *pAux, int argc, const char *const *argv, pNew->user_column_idxs[user_column_idx] = numMetadataColumns; memcpy(&pNew->metadata_columns[numMetadataColumns], &metadataColumn, sizeof(metadataColumn)); numMetadataColumns++; + pNew->numMetadataColumns = numMetadataColumns; user_column_idx++; continue; }