feat: detect unbalanced quotes in terminal commands to prevent hanging#11202
feat: detect unbalanced quotes in terminal commands to prevent hanging#11202roomote[bot] wants to merge 1 commit intomainfrom
Conversation
When a command has unbalanced quotes (missing closing quote), the shell enters continuation mode waiting for more input. Since stdin is ignored in non-interactive mode, this causes the terminal to hang indefinitely. This change: - Adds validateCommandQuotes() function in parse-command.ts to detect unbalanced single and double quotes before command execution - Correctly handles escaped quotes (\" and \') and escaped backslashes (\\) - Handles special cases like heredocs (<<EOF) and ANSI-C quoting ($'...') - Integrates validation into ExecuteCommandTool.ts to reject commands with unbalanced quotes with a helpful error message - Adds comprehensive tests for both the validation function and integration Resolves EXT-737
Review complete. Found 2 issues with the quote validation logic.
Mention @roomote in a comment to request specific changes to this pull request or fix all unresolved issues. |
| // Check for heredoc patterns which legitimately expect more input | ||
| // Common heredoc patterns: <<EOF, <<-EOF, <<'EOF', <<"EOF", << 'EOF' | ||
| const heredocPattern = /<<-?\s*['"]?\w+['"]?\s*$/ | ||
| if (heredocPattern.test(command.trim())) { | ||
| // Heredocs are valid multi-line constructs - don't flag as unbalanced | ||
| return { valid: true } | ||
| } |
There was a problem hiding this comment.
The heredoc pattern check returns early before quote validation runs. This allows commands like echo "hello && cat <<EOF to pass validation, but the shell would still hang because <<EOF appears inside an unclosed double quote string. The heredoc syntax wouldn't be recognized since the << characters are part of the quoted content. Consider moving this check after the quote validation, or only applying the heredoc exemption when quotes up to that point are balanced.
Fix it with Roo Code or mention @roomote and request a fix.
| // Handle ANSI-C quoting: $'...' - treat as single quote | ||
| if (char === "$" && i + 1 < command.length && command[i + 1] === "'") { | ||
| if (!inSingleQuote && !inDoubleQuote) { | ||
| inSingleQuote = true | ||
| singleQuoteStart = i | ||
| i += 2 // Skip $' | ||
| continue | ||
| } | ||
| } |
There was a problem hiding this comment.
The ANSI-C quoting handling sets inSingleQuote = true but doesn't distinguish it from regular single quotes. Inside ANSI-C strings ($'...'), backslash escapes work differently than in regular single quotes. For example, echo $'it\'s' is a valid command that produces it's, but the current code would incorrectly flag it as having unbalanced quotes because \' inside the string is treated as a closing quote rather than an escaped quote. Consider tracking ANSI-C mode separately and allowing \' escapes within it.
Fix it with Roo Code or mention @roomote and request a fix.
Related GitHub Issue
Closes: EXT-737
Roo Code Task Context (Optional)
View task on Roo Code Cloud
Description
When a command has unbalanced quotes (e.g.,
echo "hellowith a missing closing quote), the shell enters continuation mode waiting for more input. Since stdin is ignored in non-interactive mode (via execa), this causes the terminal to hang indefinitely.This PR addresses the issue by:
validateCommandQuotes()function inparse-command.tsthat detects unbalanced single and double quotes before command execution\"and') and escaped backslashes (\\)<<EOF) and ANSI-C quoting (`$'...'ExecuteCommandTool.tsbashImportant
Adds
validateCommandQuotesto detect unbalanced quotes in commands, preventing terminal hangs, and integrates it intoExecuteCommandTool.validateCommandQuotes()inparse-command.tsto detect unbalanced quotes in commands.ExecuteCommandToolto prevent execution of commands with unbalanced quotes.executeCommandTool.spec.tsfor unbalanced quote detection.parse-command.spec.tsforvalidateCommandQuotes()covering various edge cases and shell-specific patterns.This description was created by
for 05bf270. You can customize this summary. It will automatically update as commits are pushed.