#1152269 checkbashisms: $"..." false positive on quote-tail $ (grep/sed end-anchor) inside command substitution

Package:
devscripts
Source:
devscripts
Description:
scripts to make the life of a Debian Package maintainer easier
Submitter:
Tomáš Chvátal
Date:
2026-10-28 17:53:01 UTC
Severity:
normal
Tags:
#1152269#5
Date:
2026-10-27 11:25:37 UTC
From:
To:
checkbashisms reports a $"..." locale string where there is none:
a $ that merely ends the preceding token (a grep/sed end-anchor, or
the tail of a parameter expansion) immediately before a closing
double quote is read as the start of a $"..." string.

    #!/bin/sh
    matches="$(grep "lib" "$file" | grep "$major$" | wc -l)"

Actual output (checkbashisms 2.26.9, exit 1):

    possible bashism in test.sh line 2 ($"foo" should be eval_gettext "foo"):
    matches="$(grep "lib" "$file" | grep "$major$" | wc -l)"

The same shape with a parameter expansion (R-Matrix rules.sh):

    #!/bin/sh
    echo "$(grep "^Package: ${pkg}$" DESCRIPTION)"

also reports ($"foo" should be eval_gettext "foo").

Expected: no output. In "$major$" the $ is a BRE end-of-line anchor
inside a quoted grep pattern; $" starts a locale string only when
$" opens a string, and here it precedes the *closing* quote. Valid
POSIX sh; the pattern is data for grep.

The $'...' analogue fires on a sed/grep end-anchor at a
single-quote boundary (real instance: VFlib3 mkt1enc.sh, which also
draws a spurious "Unterminated quoted string" error; an isolated
copy of the pipeline does not trigger it — the mis-parse depends on
the checker's quote tracking earlier in that file, so the full
53-line file is the reproducer for this flavour).

[Hint: the $" check miscounts quote parity when quotes are nested
inside a command substitution; the $'...' check already suppresses
via parity counting.]

Found downstream (openSUSE/rpmlint corpus): 4 files.

Disclosure, encouraged by GR 2026-002: this report was drafted with
AI assistance; the reproducers were verified by me against
checkbashisms 2.26.9.

#1152269#10
Date:
2026-10-27 11:33:23 UTC
From:
To:
The attached patch (against devscripts master) fixes this bug. The $"
and $' checks counted quotes over the whole line prefix; quotes inside
a command substitution belong to a fresh quoting context, so a
trailing $ inside $(...) (a grep end-anchor, the tail of ${pkg}) was
misread as a locale string start. The patch counts quotes at the
current substitution level instead (new helper
count_quotes_at_current_level, used by both checks).

Regression lines added to test/bashisms/gettext.sh fail without the
patch; the suite passes with it, and genuine cases (echo $"hello
world", nested echo "$(echo $"inner")") still fire.

Scope note: the $'...' flavour in the full VFlib3 mkt1enc.sh file
could not be re-tested; the fix targets the shared counting flaw
behind both minimal reproducers.

Disclosure, encouraged by Debian GR 2026-002: prepared with AI
assistance; verified by me against the reproducers and suite.