fix(heredoc): handle unbalanced single quotes and backticks in heredoc bodies inside $(…) (#420)#1067
Merged
reubeno merged 1 commit intoreubeno:mainfrom Mar 28, 2026
Conversation
reubeno#420) The tokenizer flattens heredoc bodies into `$(...)` token text. When the body contains unbalanced single quotes or backticks, the word parser's quote-matching rules fail to consume them, causing the entire command substitution parse to fail. Add a fallback in `command_piece` so orphan `'` and `` ` `` are consumed as literal characters when `word_piece` cannot match them.
Performance Benchmark Report
Code Coverage Report: Only Changed Files listed
Minimum allowed coverage is Test Summary: bash-completion test suite
|
Owner
|
@StudioLE Thanks for another contribution, and for the detailed summary 😄 Thanks also for your patience -- I've been extremely busy and hadn't yet had time to give the change the review it deserves. I aim to get to it within the next couple of days. |
reubeno
approved these changes
Mar 28, 2026
Owner
reubeno
left a comment
There was a problem hiding this comment.
The logic behind the fix seems sound. I think there are more cases that will be problematic for us in this area (e.g., perhaps unmatched parentheses chars inside the embedded here doc?) -- but let's at least get in this fix.
takeshiD
pushed a commit
to takeshiD/brush
that referenced
this pull request
Mar 30, 2026
…c bodies inside `$(…)` (reubeno#1067) Adds a fallback in `command_piece` so orphan `'` and `` ` `` are consumed as literal characters when `word_piece` cannot match them.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #420
Test results without fix
Context
The tokenizer flattens heredoc bodies into
$(...)token text. When the body contains unbalanced single quotes or backticks, the word parser's quote-matching rules fail to consume them, causing the entire command substitution parse to fail.If you compare the snapshots of
parse_command_sub_with_unbalanced_single_quoteandparse_command_sub_with_unbalanced_backtickprior to the fix with the snapshot ofbrush_parser__word__tests__parse_command_sub_with_balanced_backticksyou can clearly see the parser is failing to match theCommandSubstitution.Solution
The solution is to add a fallback in
command_pieceso orphan'and`are consumed as literal characters whenword_piececannot match them.Caution
I believe this is safe because of PEG's ordered choice semantics: properly paired quotes are consumed by
word_piecefirst; the fallback only fires for characters no other rule can handle.However, it would be worth a maintainer validating this
Note
Unbalanced
"inside heredoc bodies within"$(…)"is a separate issue tracked in #1066. The"is consumed by the outerdouble_quoted_sequencerule beforecommand_pieceis reached, so this fix does not address it.RE: Contributor Policy
Caution
peg::parser!macro and I definitely do not have knowledge of how the macro works. Therefore I'm heavily relying on existing tests to identify if this causes regressions.