Skip to content

fix(#716): item 3 — document headless getenv path; refactor legacy guard#719

Merged
jsavin merged 2 commits into
developfrom
worktree-716-3-shellsysverbs-getenv
Jun 6, 2026
Merged

fix(#716): item 3 — document headless getenv path; refactor legacy guard#719
jsavin merged 2 commits into
developfrom
worktree-716-3-shellsysverbs-getenv

Conversation

@jsavin

@jsavin jsavin commented Jun 6, 2026

Copy link
Copy Markdown
Owner

Summary

Closes item 3 of #716 with two findings and a small refactor:

  1. The audit pointed at the wrong file. Common/source/shellsysverbs.c::getenvironmentvariablefunc is the legacy (full Mac app) impl; it is not linked into the headless frontier-cli build. The actual headless verb dispatch goes to tests/headless_sys_verbs.c::sysv_getenvironmentvariable.

  2. The headless path has no truncation surface by construction. It uses newfilledhandle + setheapvalue to return a heap-allocated string handle. There is no bigstring on this path, so the >255-byte concern raised in the issue does not apply. A regression test now locks this in.

  3. Legacy file got a small post-copyctopstring: silent truncation + buffer overflow risk on >255-byte input #707 refactor. The legacy guard worked, but it predated the post-copyctopstring: silent truncation + buffer overflow risk on >255-byte input #707 boolean-return convention. Collapsed 12 lines to 8, matching frontier-cli/window_registry.c:116 and PR fix(#716): parseerror signature now const char *; drop Pascal-string laundering #718's langerror.c:163 fix. Same observable behavior, same user-visible langerrormessage.

Changes

  • tests/headless_sys_verbs.c — expand the @IMPLEMENTED comment to document the heap-handle design intent, explicitly call out "no bigstring truncation surface here", and mark the path as "do not add a bigstring length guard" with a back-reference to copyctopstring audit tail: 6 sibling defects surfaced during #712 (bucket) #716 item 3
  • Common/source/shellsysverbs.c — refactor the legacy guard from strlen + manual >255 check + unguarded copyctopstring to the canonical post-copyctopstring: silent truncation + buffer overflow risk on >255-byte input #707 form (copyctopstring's boolean return)
  • tests/integration/sys_getenv_long_value_test.sh (new) — shell-level integration test asserting:
    • 200-byte env var reads back at length 200 (control)
    • 300-byte env var reads back at length 300 (no truncation)
    • 300-byte env var content preserved verbatim through byte 300
  • tests/Makefile — wire test-sys-getenv-long-value into test-all and .PHONY

Test plan

Scope

This PR addresses only item 3 of #716. Items 2, 4, 5 remain open and will be addressed in separate PRs:

  • 2: strings.c push-after-copyctopstring truncation
  • 4: langsqlite.c sqlite3_errmsg truncation
  • 5: tcpverbs.c / WinSockNetEvents.c INDIRECT callsites

Item 6 was already closed via PR #717's analysis.

Investigative process

I initially wrote a test that called sys.getenvironmentvariable with a >255-byte env var expecting an error (matching the original issue framing). The test returned the full 300 bytes — which surfaced that the audit target wasn't on the live path. Traced the verb dispatch through the kernel-verbs generator to tests/headless_sys_verbs.c and found the heap-handle design. The test was reframed as a regression guard for the actual headless behavior.

🤖 Generated with Claude Code

jsavin and others added 2 commits June 5, 2026 23:21
…uard

#716 item 3 audit pointed at Common/source/shellsysverbs.c:594 as a
potential truncation surface for >255-byte env vars piped through
copyctopstring. Investigation showed that file is the legacy (full Mac
app) impl, NOT linked into the headless frontier-cli build. The real
headless path is tests/headless_sys_verbs.c::sysv_getenvironmentvariable,
which uses newfilledhandle + setheapvalue to return a heap-allocated
string handle -- no bigstring, no 255-byte limit, no truncation surface
by construction.

Changes:

- tests/headless_sys_verbs.c: expand the @implemented comment to document
  the heap-handle design intent and explicitly call out that this path
  has NO bigstring truncation surface, with a back-reference to #716
  item 3 so a future audit doesn't waste cycles re-flagging it. Marks
  the path as "do not add a bigstring length guard".

- Common/source/shellsysverbs.c (legacy/full-app path): collapse the
  pre-#707 pattern (strlen + manual >255 check + unguarded copyctopstring)
  into the canonical post-#707 pattern (copyctopstring's boolean return
  with langerrormessage on truncation). Functionally equivalent -- same
  user-visible "exceeds 255 characters" error message, same return
  contract. Matches frontier-cli/window_registry.c:116 and PR #718's
  langerror.c:163 fix. Reduces the code from 12 to 8 lines and removes
  the redundant strlen.

- tests/integration/sys_getenv_long_value_test.sh + tests/Makefile:
  new shell integration test that locks in the headless behavior --
  200-byte env var reads back at length 200 (control), 300-byte env var
  reads back at length 300 with content preserved verbatim (regression
  guard against someone mistakenly applying a bigstring guard to the
  heap-handle path). 3/3 GREEN.

This PR addresses ONLY #716 item 3. Items 2, 4, 5 remain open and will
be addressed in separate PRs.

Verified:
- make build: clean
- ./tools/run_headless_tests.sh: 589/589 pass
- tests/integration/sys_getenv_long_value_test.sh: 3/3 pass
- cd tests && make test-integration: TBD (in progress as of commit)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…rkers

Security reviewer P2: original doc said "Do not add a bigstring length
guard to this path" which could be misread as forbidding any
future overflow-safety check. Tighten to "Do not add a 255-byte
bigstring length guard" and explicitly note that an overflow-safe
larger-limit check remains future-compatible.

Security reviewer P2: shell test used a uniform 'y' payload; a
length-preserving mid-buffer corruption would have passed the
length-only + final-byte assertions. Upgrade payload to 150 'A's +
150 'B's and probe at byte 150 (A), 151 (B), and 300 (B). Catches
truncation, mid-buffer corruption, and tail corruption in a single
CLI invocation (the three probes are concatenated in one --batch -e
script).

Bar-raiser P2 items (3 invocation count, strip_warnings regex
robustness, pre-existing 108-col line) declined: current
diagnosability and behavior are correct; not blocking.

Test still 3/3 GREEN.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@jsavin jsavin merged commit 523dc15 into develop Jun 6, 2026
@jsavin jsavin deleted the worktree-716-3-shellsysverbs-getenv branch June 6, 2026 09:25
@jsavin

jsavin commented Jun 6, 2026

Copy link
Copy Markdown
Owner Author

/auto Summary

What went well: The TDD-first habit caught the audit misdirection — writing the test first surfaced that the original target (Common/source/shellsysverbs.c) wasn't on the live verb-dispatch path, and led to discovering that the real headless verb (tests/headless_sys_verbs.c) uses heap handles by design. Rescoping the PR from "fix a bug" to "document the design + small legacy cleanup + lock-in regression test" was straightforward once the layout was understood.

What could improve: The original #716 audit greps for copyctopstring in Common/source/ but doesn't filter for live reachability in the headless build. The legacy Common/source/shellsysverbs.c is one of several files in that tree that are dead code in the headless target. A follow-up improvement to the audit pattern would be to cross-check each callsite against the kernel_verbs_init.c generator output before declaring a defect — for the remaining #716 items (2, 4, 5), this verification should happen first.

Recommendations: For items 4 (langsqlite errmsg) and 5 (tcpverbs INDIRECT), verify live reachability through generated/kernel_verbs_init.c before any code change. Item 2 (strings.c:1315 - string.dateString helpers) is harder to map at a glance and may warrant a dedicated reachability audit before scoping the fix.

🤖 Generated with Claude Code /auto

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