-
Notifications
You must be signed in to change notification settings - Fork 6
Description
Bug Description
execute_command_streaming() in cortex-engine/src/exec/runner.rs truncates stdout, stderr, and aggregated output using byte-index slicing (&stdout[..MAX_OUTPUT_SIZE]). This panics if the output contains multi-byte UTF-8 characters and MAX_OUTPUT_SIZE (1MB) falls inside a multi-byte character.
Location
src/cortex-engine/src/exec/runner.rs, lines 381–405 (three separate truncation sites)
Root Cause
// Line 381-386: stdout truncation
let stdout_truncated = if stdout.len() > MAX_OUTPUT_SIZE {
format!(
"{}...\n[Output truncated, {} bytes total]",
&stdout[..MAX_OUTPUT_SIZE], // BUG: byte-index slice
stdout.len()
)
} else {
stdout
};
// Line 391-396: stderr truncation (same bug)
let stderr_truncated = if stderr.len() > MAX_OUTPUT_SIZE {
format!(
"{}...\n[Output truncated, {} bytes total]",
&stderr[..MAX_OUTPUT_SIZE], // BUG: byte-index slice
stderr.len()
)
} else {
stderr
};
// Line 402-407: aggregated truncation (same bug)
let aggregated_truncated = if aggregated.len() > MAX_OUTPUT_SIZE {
format!(
"{}...\n[Output truncated, {} bytes total]",
&aggregated[..MAX_OUTPUT_SIZE], // BUG: byte-index slice
aggregated.len()
)
} else {
aggregated
};stdout, stderr, and aggregated are String values built from line-by-line reading. .len() returns byte length, and &s[..MAX_OUTPUT_SIZE] slices at a byte position that may fall inside a multi-byte UTF-8 character, causing a panic.
Note: The non-streaming truncate_output() function (line 223) has the same bug pattern with &s[..MAX_OUTPUT_SIZE] on a Cow<str> from String::from_utf8_lossy.
Reproduction
// A command that outputs >1MB of multi-byte content
// e.g., a file with CJK characters where byte 1048576 falls mid-character
// The streaming executor will panic when truncatingFix
Use floor_char_boundary or iterate chars:
let stdout_truncated = if stdout.len() > MAX_OUTPUT_SIZE {
let end = stdout.floor_char_boundary(MAX_OUTPUT_SIZE);
format!(
"{}...\n[Output truncated, {} bytes total]",
&stdout[..end],
stdout.len()
)
} else {
stdout
};Apply the same fix to all four truncation sites (3 in streaming + 1 in truncate_output).
Impact
When a shell command produces >1MB of output containing multi-byte UTF-8 characters (e.g., cat on a large internationalized file, build output with Unicode paths), the executor panics. This crashes the tool execution and breaks the agentic loop. Since MAX_OUTPUT_SIZE is 1MB, this is triggered whenever large multi-byte output is produced by any shell command.
Version
v0.1.0