Repository navigation
SC2075: a backslash inside single quotes is literal — no false positive on '\\' followed by another quoted string (#439) - #441
Merged
Conversation
Inside '...' a backslash is literal and the next quote closes the
string. SC2075 matches '[^']*\\'[^']*' on the raw line, so in
echo 'a\b' | tr -d '\\' | grep -x 'ab'
it reads the quote after '\\' as escaped and pairs the string with the
next quoted string on the line: an Error (2:20-36) on a script bash
runs and prints "ab".
Tests, all failing on this commit:
- the reproducer, the lone-backslash form tr -d '\' | grep -x 'a', and
the same pipeline inside "$( ... )" report no SC2075 and no error
(sc2075 unit tests, and end to end through lint_shell in
lexer_context_tests);
- a backslash string followed by a separate word: a space, ';', ']',
'"', '$', another quote, a trailing comment;
- \' outside a plain single-quoted string: "it\'s", $'it\'s', it\'s;
- echo 'it\'s' still reports SC2075 as an Error, also after an earlier
valid '\\' on the same line, and echo 'a\'1 (no later quote) too.
The issue's controls (tr -d '\\' alone, x='\\', x='\') and the ten
existing SC2075 tests pass. F-LCX-021 in linter-lexer-context-v1 names
the end-to-end test.
Pmat-Ticket: PMAT-439
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The rule matched '[^']*\\'[^']*' on the raw line. That reads every \' as an escaped quote, so tr -d '\\' | grep -x 'ab' became one string running from '\\' to the next opening quote on the line, an Error on a valid script. It now scans each line with its quoting context. Inside '...' a backslash is literal and the next quote closes the string; the attempt it reports is a \' followed straight away by a letter, digit or underscore, as in 'it\'s', where the closing quote runs into the same word. \' inside "...", $'...', a comment or unquoted code is not read as one. After an attempt the scan reads the string the way its author meant it, so 'don\'t' 'won\'t' still reports twice; linter::quoting reads the line as the shell does and closes at the \', which puts it out of step with the author for the rest of the line, so the rule does not use it. The ten existing SC2075 tests keep their counts and spans. Putting the regex back turns all seven PMAT439 tests red; with this change all 18 SC2075 tests pass. The highest cyclomatic complexity in the file is 7. Pmat-Ticket: PMAT-439 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
awk -F'\' '{print $2}' file splits on a backslash. The old regex read
'\' '{print $2}' as one string with an escaped quote in it; the rule
now reports nothing there, and a row holds it.
An attempt followed by a space, echo 'can\' t', glues no word, so
SC2075 stays silent on it. The quote it leaves open is still an Error
from SC1078, and lexer_context_tests now asserts that, so narrowing
SC2075 to the word-gluing case does not let that line go clean.
Pmat-Ticket: PMAT-439
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
echo 'a\'b has no later quote on the line, so the shell's reading is the only one: the string a\ closes and the word runs on into b, printing a\b. The old regex needed a later quote before it reported, but the scanner reported this valid line as SC2075. It now records an attempt only when a later quote closes the string its author meant, which keeps echo 'it\'s' and the digit form echo 'a\'1' reported. $$ is the pid, so in echo $$'a\'b' the quote after it opens a plain single-quoted string. The scanner read $' there as ANSI-C quoting and went silent where the old regex reported. $$ is now stepped over as one token. Pmat-Ticket: PMAT-439 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The receipt maps each claim to its test, gives the RED and revert counts, the gate counts and the corpus score, and lists what the fix does not cover. The review record holds both blind rounds: each lane's verdict on the real diff and on a control, and the cargo result for each control. Pmat-Ticket: PMAT-439 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
noahgift
added a commit
that referenced
this pull request
Oct 10, 2026
…g from main carries, including the SC2075 fix forjar's I8 gate is waiting on (#442) The second cut (#416) was not tagged, and two fixes merged after it: #430 (PMAT-428, SEC012 follows an eval payload through a variable) and #441 (PMAT-439, SC2075 false positive on '\\' followed by another quoted string). A tag cut from main carries both, so CHANGELOG, release-notes, releases.md and the book name fifteen fixes, both entries are completed with release:v7.4.2, and PMAT-354 gains the third-cut criterion. Docs-only. Measured on e25dbee (debug build): the completion check of fw16-wired-10g-nm-owner from infra origin/main lints 0 errors (7.4.1: 1 error, SC2075 at 6:99-116), and `echo 'don\'t'` still fires SC2075. Refs PMAT-354 Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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 #439.
bashrs lintreported SC2075 [error] ("Escaping a single quote in single quotes won't work") on a valid single-quoted backslash when another single-quoted string followed on the same line:Inside single quotes a backslash is literal, so
'\\'and'\'close normally. The rule now reports an attempt to escape a single quote only when the string the author meant actually closes later on the line, and treats a backslash before a closing single quote as literal. The true positiveecho 'it\'s'still fires.Commits:
"$( ... )", and the true positives.rash/src/linter/rules/sc2075.rs, plus pins forawk -F'\'and the open quote an attempt leaves (SC1078 control).docs/audits/impl-PMAT-439-receipt.md) and review record (docs/audits/quorum-PMAT-439-review.json).Evidence (in the receipt): targeted tests 18 passed / 0 failed; with the rule body reverted and the tests kept, 7 fail;
cargo nextest run --workspace17347 passed / 0 failed;bashrs corpus run18814/18814;pv lint contractsPASS. Two blind review rounds, each 3/3 PASS on the real diff with a planted control caught 3/3.Pmat-Ticket: PMAT-439
🤖 Generated with Claude Code