Skip to content

fix(analyzer): keep checking command lines inside a word that spans lines - #814

Open
elliottwaves-20 wants to merge 1 commit into
NVIDIA:mainfrom
elliottwaves-20:fix/multiline-word-shadow
Open

elliottwaves-20 wants to merge 1 commit into
NVIDIA:mainfrom
elliottwaves-20:fix/multiline-word-shadow

Conversation

@elliottwaves-20

Copy link
Copy Markdown

Fixes #813.

Problem

A double quote in a heredoc body, a shell comment or Markdown prose can pair with a quote on a later command line. _has_shell_command_word_exhaustion then parses one word across those lines and moves parsed_through past it. Every candidate inside the word is skipped, including a runtime-selected command such as $CMD"" -rf /, and the file is reported as completely inspected. The reproducers are in #813.

Change

The fix does not try to prove shell quote state. It only stops a multi-line word from hiding later command lines.

  • A parsed word that spans a line break (LF or lone CR) opens a shadow region (shadow_through) instead of moving parsed_through.
  • Candidates inside the region are still parsed and checked, but only at a command position: line start, or after ;, |, & or ( (new helper _is_shell_command_position). That keeps the extra parse work linear in the number of lines, and test_json_owned_runtime_bounds.py still passes.
  • Shadowed candidates never own quotes and never move parsed_through or shadow_through. An unresolved parse inside the region is not charged to the command-word budget, because the spanning word already closed that region's quotes.
  • Python sources (python_source is not None) keep the current frontier, because the AST already proves their string and comment bounds.

The candidates after the region are therefore the same as on main, and the region's candidates can only add checks. No file can move from partial to complete.

Tests

tests/nodes/analyzers/test_multiline_word_shadow.py:

  • test_quote_spanning_lines_cannot_hide_a_later_command: comment, heredoc with plain and quoted delimiter, ${X}, ${X}" ", $()"e", a backtick variant, lone-CR line endings, and Markdown prose into a fence. Each runs short and padded. All fail on main.
  • test_heredoc_quote_cannot_hide_a_runtime_rm_at_scan_level: the run.sh from Quote in a heredoc body, comment or prose hides a later command line from the command-word scan #813 through run_static_patterns_with_ledger, expected to be not COMPLETED.
  • Pins for unchanged behavior: a multi-line echo "…$HOME" stays complete, a dynamic multi-line $(…) word behaves as on main, and Python sources keep their frontier.

Verification against main 5edc347

  • Full suite: the set of failing tests is identical on main and on this branch. Those failures are Windows/environment-specific on my machine (release, git and CLI tests).
  • Corpus of about 3,600 skill files: no file moves from partial to complete, and no file loses a TM1 finding. 4 files move from complete to partial (3 distinct). All are Markdown where a prose quote pairs across lines into a later block, so main skipped those lines.
  • Differential fuzzing, 100k generated shell snippets with heredoc, comment and adjacent-quote shapes: 0 cases where main is partial and this branch is complete.

🤖 Generated with Claude Code

…ines

A quote in a heredoc body, a shell comment or Markdown prose can pair with
a quote on a later command line. The command-word scan then parsed one word
across those lines and skipped every candidate inside it, so a runtime
command such as

    cat <<E
    he said "hi
    E
    $CMD"" -rf / # "

was reported as completely inspected.

A word that spans a line break now opens a shadow region instead of moving
the parse frontier. Candidates in that region are still checked at command
positions (line start or after ; | & (), but they never own quotes, never
move the frontier, and an unresolved parse there is not charged to the
budget. Python sources keep their AST-proven frontier. Later candidates are
the same as on main, so the result is never less strict than main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: elliottwaves-20 <pail1217@web.de>
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.

Quote in a heredoc body, comment or prose hides a later command line from the command-word scan

1 participant