Skip to content

Fix OOB read on metadata IN filter path (size_t -> int) - #318

Open
stumpylog wants to merge 1 commit into
asg017:mainfrom
stumpylog:fix/metadata-in-oob-read
Open

Fix OOB read on metadata IN filter path (size_t -> int)#318
stumpylog wants to merge 1 commit into
asg017:mainfrom
stumpylog:fix/metadata-in-oob-read

Conversation

@stumpylog

@stumpylog stumpylog commented Sep 1, 2026

Copy link
Copy Markdown

Summary

vec0's metadata IN (...) filter path (VEC0_METADATA_OPERATOR_IN in vec0_metadata_filter_text) declares:

size_t metadataInIdx = -1;

size_t is unsigned, so this wraps to SIZE_MAX. The subsequent not-found guard:

if (metadataInIdx < 0) {
  rc = SQLITE_ERROR;
  goto done;
}

is dead code for an unsigned type — it can never fire. If the constraint lookup doesn't find a matching entry, execution falls through and indexes aMetadataIn with SIZE_MAX, an out-of-bounds read. The parallel IN handling in the same file (vec0_filter, a few hundred lines down) already declares this as int for the same reason — this is a case where the two IN code paths drifted apart.

Fix

Change metadataInIdx to int, matching the already-correct sibling path. The guard now does what it always looked like it did.

Testing

Added test_metadata_in_filter to tests/test-metadata.py, exercising a label IN (...) metadata filter with a full round-trip on a small vec0 table.

🤖 Generated with Claude Code

VEC0_METADATA_OPERATOR_IN declared `size_t metadataInIdx = -1`, which wraps
to SIZE_MAX. The subsequent `if (metadataInIdx < 0)` not-found guard is dead
code for an unsigned type, so a missing entry fell through to an out-of-bounds
read indexing the metadata-IN array. The parallel path already uses `int`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant