Skip to content

fix(parser): heredoc backslash escapes; read without -r - #2581

Merged
chaliy merged 1 commit into
mainfrom
claude/heredoc-read
Oct 7, 2026
Merged

chaliy merged 1 commit into
mainfrom
claude/heredoc-read

Conversation

@chaliy

@chaliy chaliy commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Requested by Михайло · project thread

What changed

  • Unquoted heredoc bodies handle backslashes like bash. \$, \` and \\ are literal, \<newline> joins lines (also inside $((…))), other backslashes stay, and backtick substitution runs.
  • read without -r removes backslashes. An escaped IFS character stays inside its field (read a b <<< 'x\ y z' gives a='x y'), and \<newline> joins the next line.
  • read returns 1 when input ends before the delimiter but still assigns the data (printf abc | read v). An empty stdin returns 1.
  • A read from a shared pipe ({ read; read; }, while read) now consumes one record that honours -d, -n and continuation. Before, it always took one line.

Why

Oracle failures shell/heredoc-expand and shell/read-options from the pseudo-linus list.

Before / After

Script Before After (= bash 5.2)
heredoc line literal \$user e \crase`` literal \agente e \crase`` literal $user e `crase`
heredoc line `echo bt` `echo bt` bt
read a <<< 'barra\invertida' barra\invertida barrainvertida
read nada < /dev/null; echo $? 0 1
printf 'a;b' | { read -d ';' p; read -d ';' q; echo $p $q; } first read took the whole line a b

New spec heredoc-read-escapes.test.sh has 5 cases, all verified against bash. Read unit tests that fed unterminated input and expected status 0 now pass newline-terminated input, since bash returns 1 for unterminated input.

Risk

Medium. read status at EOF changes for unterminated input, matching bash; the while read || [ -n "$l" ] idiom keeps working (covered). All lib, integration and bash_comparison tests pass.

Checklist

  • Tests (spec, verified against bash)
  • cargo fmt, cargo clippy -D warnings
  • lib, integration and bash_comparison tests
  • Docs (compatibility.md) and knowledge log updated

https://claude.ai/code/session_019aFikmptPc91Fj4N2iDXQA


Generated by Claude Code

Unquoted heredoc bodies treat \$, \` and \\ as literals, join
\<newline> lines and run backtick substitution. `read` without -r
removes backslashes, joins continued lines, and returns 1 when input
ends before the delimiter. Pipe consumption follows -d/-n.

Claude-Session: https://claude.ai/code/session_019aFikmptPc91Fj4N2iDXQA
@chaliy chaliy self-assigned this Oct 7, 2026
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
bashkit 9f3bf78 Commit Preview URL

Branch Preview URL
Oct 07 2026, 05:57 PM

@chaliy
chaliy merged commit 81af23a into main Oct 7, 2026
47 checks passed
@chaliy
chaliy deleted the claude/heredoc-read branch October 7, 2026 18:16
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.

1 participant