fix: bash shell integration use-after-free bug

The ShellCommandBuilder uses a stackFallback allocator, which means
toOwnedSlice() may return memory allocated on the stack. When setupBash()
returns, this stack memory becomes invalid, causing a use-after-free.

This manifested as garbage data in the shell command string, often
appearing as errors like "/bin/sh: 1: ically: not found" (where "ically"
was part of nearby memory, likely from the comment "automatically").

The fix copies the command string to the arena allocator before returning,
ensuring the memory remains valid for the lifetime of the command.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
pull/9885/head
Michael Bommarito 2025-12-12 13:36:36 -05:00
parent dd06d8a13b
commit 2d9c83dbb7
1 changed files with 5 additions and 1 deletions

View File

@ -353,7 +353,11 @@ fn setupBash(
);
try env.put("ENV", integ_dir);
return .{ .shell = try cmd.toOwnedSlice() };
// Get the command string from the builder, then copy it to the arena
// allocator. The stackFallback allocator's memory becomes invalid after
// this function returns, so we must copy to the arena.
const cmd_str = try cmd.toOwnedSlice();
return .{ .shell = try alloc.dupeZ(u8, cmd_str) };
}
test "bash" {