Skip to content

chore(vector): assert that setValue writes the vector's value size - #1464

Open
zahariash wants to merge 2 commits into
LadybugDB:mainfrom
zahariash:chore/setvalue-size-guard
Open

zahariash wants to merge 2 commits into
LadybugDB:mainfrom
zahariash:chore/setvalue-size-guard

Conversation

@zahariash

Copy link
Copy Markdown
Contributor

This work was produced with the help of language models.

Stacked on #1463; only the last commit is new. Depends on LadybugDB/extensions#141: the minimal linux extension test job fails on the new assertion until that fix merges and the extension submodule includes it. The submodule bump is added here as a commit once it merges, and CI is re-run then.

ValueVector::setValue<T> indexes the value buffer as an array of T, so a T of another size writes into the wrong slots without an error. That is how union_value damaged its rows' positions in #1425: 2-byte tags went into a vector of 8-byte positions. setValue now asserts that sizeof(T) is the vector's value size. Release builds compile it out unless RUNTIME_CHECKS is set.

Callers. CompressChunkTest.TestDoubleInPlaceUpdateNoExceptions filled a FLOAT vector with doubles for a DOUBLE chunk and tripped it; it now uses a DOUBLE vector. The fts extension wrote a new term's df as an int into a UINT64 vector. No other engine test trips it.

Tests. value_vector_test.cpp checks that a 2-byte write into a union vector throws and keeps the row's position, that an INT64 write into an INT32 vector throws, and that matching writes go through. With main's union_value, union.test fails on the assertion. Without LadybugDB/extensions#141, the fts e2e tests fail 11 cases on the assertion, and the half-applied inserts then crash a later query, a separate exception-safety problem. With it, 86 of the 87 pass; show_loaded_extensions also needs the duckdb extension, which the run did not build. Full ctest: 3229/3229.

zahariash and others added 2 commits November 2, 2026 01:09
UnionVector::setTagField stored the tag as a uint16 in the union
vector's own data, which holds each row's struct_entry_t position in
the field vectors. For an unfiltered chunk of n rows it zeroed the
positions of rows 1 to ceil(n/4) - 1, and the result vector is
reused, so later chunks kept the damage. Everything that follows
those positions read position 0: list literal, list_append and map
copies, CAST to STRING and comparisons. [union_value(a := i)]
returned [1] for i = 2, and 1,022 of 3,000 rows held another row's
value. union_extract and a plain RETURN read the field vectors at the
row's own position and were right.

The tag now goes into the tag vector, as the cast and JSON paths do.
union_value builds a one-member union, so the tag is 0, which the
never-written tag vector already returned from its zero-filled
buffer. union_value names that member index instead of passing
UnionType::TAG_FIELD_IDX, the tag's position among the struct fields.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ValueVector::setValue<T> indexes the value buffer as an array of T,
so a T of another size lands in the wrong slots without an error, as
union_value's tags did. It now asserts that sizeof(T) is the vector's
value size, which throws in runtime-check builds.

CompressChunkTest.TestDoubleInPlaceUpdateNoExceptions tripped it: it
filled a FLOAT vector with doubles for a DOUBLE chunk, and now uses a
DOUBLE vector. The fts extension trips it as well, by writing a new
term's df as an int into a UINT64 vector, so the extension fix and its
submodule bump have to land first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@zahariash
zahariash force-pushed the chore/setvalue-size-guard branch from f494320 to e94b26b Compare November 2, 2026 00:09
@zahariash
zahariash marked this pull request as ready for review November 11, 2026 12:29

This branch has not been deployed

No deployments
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