From 2d9c83dbb7ee50471f8326f3687651d2a944c350 Mon Sep 17 00:00:00 2001 From: Michael Bommarito Date: Fri, 12 Dec 2025 13:36:36 -0500 Subject: [PATCH] fix: bash shell integration use-after-free bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/termio/shell_integration.zig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/termio/shell_integration.zig b/src/termio/shell_integration.zig index 128b345ea..71492230e 100644 --- a/src/termio/shell_integration.zig +++ b/src/termio/shell_integration.zig @@ -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" {