Skip to content

fix(update): correct scalar-broadcast for GUID/STR and all column widths#252

Merged
singaraiona merged 1 commit into
masterfrom
fix/update-typed-column-broadcast
Jun 13, 2026
Merged

fix(update): correct scalar-broadcast for GUID/STR and all column widths#252
singaraiona merged 1 commit into
masterfrom
fix/update-typed-column-broadcast

Conversation

@singaraiona

Copy link
Copy Markdown
Collaborator

Follow-up to #250, which merged before this commit was pushed — so the update portion of that audit never landed. This carries it forward unchanged onto current master.

Problem

ray_update broadcasts a scalar atom into a full column through a fixed 8-byte elem stack buffer with a (ct==BOOL)?1:8 stride. For a GUID column (16-byte payload, stored in ->obj) ray_vec_append then reads 16 bytes from the 8-byte buffer — an ASan stack-buffer-overflow / crash — and it also copies from the wrong source field (->i64 instead of ->obj). The narrow-int and temporal types only worked by relying on union aliasing on little-endian.

Repro (crashes under ASan before the fix):

(set t (table [k a] (list [1 2 3] (guid 3))))
(update {a: (first (guid 1)) from: 't})

Fix

All three broadcast sites (WHERE, all-rows, and the BY new-column path) now use a 16-byte buffer, copy ray_elem_size(ct) bytes, and source GUID payloads from ->obj. The BY new-column site also gained the STR handling the other two already had, so a string-valued new column no longer copies garbage.

alter (store_typed_elem) and upsert/insert (handled in #250) already cover every type.

Tests

Added update-broadcast regression tests to table/update.rfl: I32/I16/Date/Timestamp type preservation, plus the GUID overflow (all-rows and WHERE).

Full suite green (make test, 0 failed).

ray_update broadcast a scalar atom into a full column through a fixed
8-byte `elem` buffer with a (ct==BOOL?1:8) stride. For a GUID column
(16-byte payload, stored in ->obj) ray_vec_append then read 16 bytes from
the 8-byte stack buffer — an ASan stack-buffer-overflow / crash — and it
also copied from the wrong source field (->i64 instead of ->obj). The
narrow-int and temporal types only worked by relying on union aliasing
on little-endian.

All three broadcast sites (WHERE, all-rows, and the BY new-column path)
now use a 16-byte buffer, copy ray_elem_size(ct) bytes, and source GUID
payloads from ->obj. The BY new-column site also gained the STR handling
the other two already had, so a string-valued new column no longer copies
garbage.

alter (store_typed_elem) and upsert (append_atom_to_col + ray_elem_size
copy loop, fixed earlier in this branch) already handle every type.

Added update-broadcast regression tests covering I32/I16/Date/Timestamp
type preservation and the GUID overflow (all-rows and WHERE).
@singaraiona singaraiona merged commit 4bbfa3c into master Jun 13, 2026
4 checks passed
@hetoku hetoku deleted the fix/update-typed-column-broadcast branch June 13, 2026 13:50
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