Skip to content

fix(subprocess): NUL-terminate cbm_build_win_cmdline buf on overflow (post-review, follow-up to #881)#889

Merged
DeusData merged 1 commit into
DeusData:mainfrom
Flipper1994:fix/subprocess-cmdline-overflow-contract
Jul 5, 2026
Merged

fix(subprocess): NUL-terminate cbm_build_win_cmdline buf on overflow (post-review, follow-up to #881)#889
DeusData merged 1 commit into
DeusData:mainfrom
Flipper1994:fix/subprocess-cmdline-overflow-contract

Conversation

@Flipper1994

Copy link
Copy Markdown
Contributor

Summary

Small post-review tidy — follow-up to #881 (already merged). Pure polish: no functional change for any real input.

The one substantive fix

cbm_build_win_cmdline() (src/foundation/subprocess.c) returns false from inside its loop on buffer overflow without NUL-terminating buf, although its header contract in subprocess.h says the buffer holds a string. There is no live bug — both call sites (cbm_run_win and the UI http_server index spawn) ignore buf when the function returns false — but a future caller trusting the documented contract could read an unterminated (possibly uninitialized) buffer. This sets buf[0] = '\0' on the overflow path so buf is always a valid string, and corrects the header comment to match.

Also (same files, same review pass)

  • Fix the stale cbm_cmdline_put comment — it returns pos unchanged on overflow; the overflow is signalled via *ovf, not via an advancing pos.
  • Bounds-guard the reference CommandLineToArgvW parser in the round-trip test (tests/test_subprocess.c) so a hypothetical future over-long test argument fails safely instead of overflowing its 256-byte row.

These came out of an adversarial self-review of #881 after it had already merged; landing them per the boy-scout rule rather than leaving a contract inaccuracy in a public function.

Refs #881.

@DeusData

DeusData commented Jul 5, 2026

Copy link
Copy Markdown
Owner

This is great, @Flipper1994 — the fix is spot on: buf[0] = '\0' on the overflow path (and I see the real '\0', not the ' ' from your note 👍), the header doc now matches, and the cbm_cmdline_put comment correction is accurate — it does return pos unchanged on overflow, so the old "pos keeps advancing" line was genuinely stale. The PUTO bounds-guard on the reference parser is a nice touch too.

One thing before we merge, to match our reproduce-first convention: this still needs a test that is RED on current main and green with the fix. The PUTO guard hardens the reference parser but doesn't exercise the actual contract (overflow → buf terminated). Something like:

TEST(win_cmdline_overflow_leaves_empty_string) {
    char buf[8];
    const char *const argv[] = {"averylongprogramname", "x", NULL};
    ASSERT_FALSE(cbm_build_win_cmdline(buf, sizeof(buf), argv)); /* overflows cap */
    ASSERT_EQ(buf[0], '\0'); /* RED on unfixed: buf[0] holds a partial byte, not NUL */
    PASS();
}

On the pre-fix code buf[0] is the first quoted byte (not '\0'), so it fails; with your fix it passes — that's the guard that proves the contract and locks it in. Register it in the suite and this is good to go. Everything else looks clean.

Follow-up to DeusData#881. cbm_build_win_cmdline() returned false from inside its loop on
buffer overflow without NUL-terminating buf, although its header contract states the
buffer holds a string. No live bug — both call sites (cbm_run_win and the UI
http_server index spawn) ignore buf when the function returns false — but a future
caller trusting the documented contract could read an unterminated (possibly
uninitialized) buffer. Set buf[0]='\0' on the overflow path so it is always a valid
string, and correct the header comment to match.

Reproduce-first: the new win_cmdline_overflow_leaves_empty_string test feeds an argv
that overflows a small cap and asserts buf[0]=='\0'. It is RED on the pre-fix code
(buf[0] holds the first quoted byte '"' = 0x22) and GREEN with the fix.

Also tidies two review nits in the same files:
- fix the stale cbm_cmdline_put comment (it returns pos UNCHANGED on overflow;
  the overflow is signalled via *ovf, not an advancing pos),
- bounds-guard the reference CommandLineToArgvW parser in the round-trip test.

Refs: DeusData#881
Signed-off-by: Flipper <jacobphilipp@ymail.com>
@Flipper1994 Flipper1994 force-pushed the fix/subprocess-cmdline-overflow-contract branch from 10d5268 to a57d8e3 Compare July 5, 2026 15:42
@Flipper1994

Copy link
Copy Markdown
Contributor Author

Done — added win_cmdline_overflow_leaves_empty_string exactly as you sketched and registered it in the suite. Verified the reproduce-first property locally: on the pre-fix code it's RED (buf[0] == 34, i.e. the leading ", not '\0'), and it goes green with the buf[0] = '\0' fix. Kept both comment corrections in this PR as you asked. Pushed — thanks for the sharp review 🙏

@DeusData DeusData marked this pull request as ready for review July 5, 2026 16:55
@DeusData DeusData self-requested a review as a code owner July 5, 2026 16:55
@DeusData DeusData merged commit fea48a5 into DeusData:main Jul 5, 2026
18 checks passed
@DeusData

DeusData commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Merged (fea48a50) — thank you! Clean overflow-contract fix with a genuine reproduce-first guard. 🙏

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.

2 participants