Skip to content

fix(store): read full link sidecar to avoid wrong-symbol truncation#334

Merged
singaraiona merged 2 commits into
RayforceDB:devfrom
belowzeroff:fix/col-link-sidecar-truncation
Jul 18, 2026
Merged

fix(store): read full link sidecar to avoid wrong-symbol truncation#334
singaraiona merged 2 commits into
RayforceDB:devfrom
belowzeroff:fix/col-link-sidecar-truncation

Conversation

@belowzeroff

Copy link
Copy Markdown
Contributor

What & why

try_load_link_sidecar (src/store/col.c) read a linked column's target table
sym name into a fixed 256-byte stack buffer (fread of 255 bytes). A target
name longer than 255 bytes was silently truncated, so ray_sym_intern interned
a different symbol and the loaded column linked to the wrong table
silent data corruption across a save/load round-trip. The writer side already
emits the full, untruncated name, so only the reader was capping.

(The 255 limit in sym.c bounds the number of dot-separated segments, not
the byte length of a name, so names longer than 255 bytes are legal and
reachable.)

The fix reads the whole sidecar into a buffer sized to the file, capped at 1 MiB
so a corrupt/oversized sidecar can't force a large allocation, using the
ray_alloc_raw / ray_free_raw pair already used elsewhere in the file. The
trailing-whitespace trim and best-effort semantics (any failure leaves the
column unlinked) are preserved.

Test

link/persistence_long_target_name links a column through a 300-byte target
name, saves, loads, and asserts the loaded link_target still resolves to the
original symbol. Verified as a genuine regression test — with the old reader the
suite reports:

link/persistence_long_target_name   FAIL
=== 3631 of 3633 passed (1 skipped, 1 failed) ===

and with the fix it passes.

Full suite under the debug ASan + UBSan build: 3632 of 3633 passed (1 skipped, 0 failed).

Checklist

  • PR targets dev (not master)
  • Commits follow Conventional Commits (fix:)
  • make builds cleanly (no new warnings)
  • make test passes; tests added/updated for behaviour changes

@singaraiona

Copy link
Copy Markdown
Collaborator

Please reject a short read before trimming or interning. fread may return 0 < n < fsz on an I/O error or if the sidecar is truncated after ftell; the current code then interns that prefix and sets HAS_LINK, recreating the wrong-symbol linkage this patch is intended to prevent. After closing the file, check n == (size_t)fsz; otherwise free buf and return.

try_load_link_sidecar read the target table's sym name into a fixed
256-byte buffer (fread of 255 bytes). A name longer than 255 bytes was
silently truncated, so ray_sym_intern interned a DIFFERENT symbol and the
loaded column linked to the wrong table — silent data corruption on a
save/load round-trip. The writer already emits the full, untruncated name.

Read the whole sidecar into a buffer sized to the file (capped at 1 MiB to
bound a corrupt/oversized file), and reject a short read (fread returning
fewer bytes than the file size — an I/O error or a race-truncated sidecar)
so a partial name can't be interned as a different symbol either.

Add a regression test that links through a 300-byte target name and asserts
the loaded link_target matches; it fails without the fix.
@belowzeroff
belowzeroff force-pushed the fix/col-link-sidecar-truncation branch from 6c29a63 to 1c63994 Compare July 18, 2026 15:42
@belowzeroff

Copy link
Copy Markdown
Contributor Author

Thank you. Added an explicit n == fsz short-read check before trimming/interning; a partial read now frees the buffer and leaves the column unlinked. Amended in 1c63994.

@singaraiona
singaraiona merged commit 7475949 into RayforceDB:dev Jul 18, 2026
9 checks passed
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.

3 participants