Skip to content

syntax: fix parsing a quoted $# in zsh - #1406

Closed
StudentWeis wants to merge 1 commit into
mvdan:masterfrom
StudentWeis:fix-zsh-quoted-dollar-hash
Closed

StudentWeis wants to merge 1 commit into
mvdan:masterfrom
StudentWeis:fix-zsh-quoted-dollar-hash

Conversation

@StudentWeis

Copy link
Copy Markdown

Fixes #1405.

The problem

In Zsh mode, a double quote directly following $# in the short form
was treated as the start of a quoted parameter name. The parser then
consumed both the # and the " as a length prefix, failed to parse
a parameter name afterwards, and the expansion collapsed to a bare $:

$ printf 'if [ "$#" -lt 2 ]; then\n\techo "$#"\nfi\n' | shfmt -ln=zsh  # before
if [ "$" -lt 2 ]; then
	echo "$"
fi

This silently changes semantics, as $ expands to the shell PID in Zsh,
and zsh -n cannot detect it.

Root cause

paramNameStart accepted " as the start of a parameter name, which
is correct for the long form, where Zsh nested expansions in quotes
like ${#"${foo}"} exist (#1214). But in the short form the " is
never part of the expansion: real Zsh treats "$#" as the special
parameter, and $#"$foo" as $# followed by a quoted word:

% set -- x y; echo "$#"; echo $#"foo"
2
2foo

The same applied to the % and + short prefixes.

The fix

Pass whether the expansion is the short form into paramNameStart and
refuse a leading " in that case. The long form keeps accepting
quoted parameter names, so ${#"${foo}"} still parses as before.

Added parser regression tests for "$#" and $#"$foo".

In the short form like "$#", a double quote directly following the
special parameter name was treated as the start of a parameter name,
so $# consumed the quote as a length prefix and failed to parse a name
afterwards, printing just $. Real Zsh treats "$#" as the special
parameter and $#"$foo" as $# followed by a quoted word, so only the
long form like ${#"${foo}"} can start a quoted parameter name.
The same applied to the % and + short prefixes.

Fixes mvdan#1405.
@StudentWeis
StudentWeis force-pushed the fix-zsh-quoted-dollar-hash branch from 1f10f58 to 9b0f0bc Compare August 29, 2026 11:01
@mvdan

mvdan commented Aug 31, 2026

Copy link
Copy Markdown
Owner

See: 019025c

@mvdan mvdan closed this Aug 31, 2026
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.

zsh: quoted "$#" is corrupted to "$" (silent semantic change)

2 participants