Skip to content

SONARJAVA-6826: Implemented rule S9359 (Octal escape sequences should not be followed by digits) - #6008

Merged
romainbrenguier merged 6 commits into
masterfrom
romain/new-rule-s9359-sonarjava-6826
Aug 25, 2026
Merged

SONARJAVA-6826: Implemented rule S9359 (Octal escape sequences should not be followed by digits)#6008
romainbrenguier merged 6 commits into
masterfrom
romain/new-rule-s9359-sonarjava-6826

Conversation

@romainbrenguier

Copy link
Copy Markdown
Contributor

This PR implements rule S9359 which detects octal escape sequences in string literals that are followed by additional digits, creating ambiguity about the intended character sequence.

The rule identifies patterns like '\128' where it's unclear whether this represents octal escape '\12' followed by literal '8', or a malformed escape sequence. This can lead to confusion and potential bugs in string handling code.

Changes:

  • Added OctalEscapeSequenceFollowedByDigitCheck.java with detection logic
  • Added comprehensive test cases in OctalEscapeSequenceFollowedByDigitCheckSample.java
  • Added unit tests in OctalEscapeSequenceFollowedByDigitCheckTest.java
  • Added rule metadata files (S9359.html, S9359.json, Sonar_way profile)

… not be followed by digits)

This rule detects octal escape sequences in string literals that are followed by additional digits, which can create ambiguity about the intended character sequence. The rule identifies patterns like '\128' where it's unclear whether this represents octal escape '\12' followed by literal '8', or a malformed escape sequence.

Files added:
- OctalEscapeSequenceFollowedByDigitCheck.java: Rule implementation
- OctalEscapeSequenceFollowedByDigitCheckTest.java: Unit tests
- OctalEscapeSequenceFollowedByDigitCheckSample.java: Test samples
- S9359.html, S9359.json: Rule metadata
@hashicorp-vault-sonar-prod

hashicorp-vault-sonar-prod Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

SONARJAVA-6826

@datadog-sonarsource

This comment has been minimized.

romainbrenguier and others added 2 commits August 24, 2026 13:19
- Remove backslash from isAmbiguousFollowUp to avoid false positive on
  consecutive octal escapes like "\1\2"
- Replace newlines with space instead of empty string in text block
  handling to avoid false positives when octal escapes span lines
- Remove misaligned column markers from test sample to match
  full-node issue reporting
- Add compliant test case for consecutive octal escapes
- Set quickfix metadata to "infeasible" instead of "unknown"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Reduce cognitive complexity of visitNode by extracting
  containsOctalFollowedByDigit and processBackslash helper methods
- Eliminate multiple continue statements by using if/else-if/else
- Add test cases for text blocks, edge cases, and improved coverage

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
romainbrenguier and others added 2 commits August 24, 2026 14:14
…ith digits 4-7

Java only allows 2-digit octal escapes when the first digit is 4-7 (e.g., \45),
but the rule was treating them as 3-digit escapes. This caused false negatives
like "\456" not being flagged (Java parses it as \45 followed by '6').

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@romainbrenguier
romainbrenguier marked this pull request as ready for review August 24, 2026 13:25

@nathsou nathsou left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One blocking issue

</pre>
<h4>Compliant solution</h4>
<pre data-diff-id="1" data-diff-type="compliant">
String message = "Error code: \u000A" + "8";

@nathsou nathsou Aug 24, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This “Compliant solution” does not compile. Java translates Unicode escapes before tokenization, so \u000A becomes a physical newline inside the string and javac reports unclosed string literal.

image

https://dev.java/p?id=a60ce0e9e604cdf41b8e4ac6

Prefer named escape sequences over Unicode escapes in fix guidance,
and update quickfix status to unknown.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gitar-bot

gitar-bot Bot commented Aug 25, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 4 resolved / 4 findings

Implements static analysis rule S9359 to detect octal escape sequences followed by digits, resolving issues with ambiguous parsing, text block newlines, and precise test markers. No issues found.

✅ 4 resolved
Bug: Backslash treated as ambiguous flags valid consecutive octal escapes

📄 java-checks/src/main/java/org/sonar/java/checks/OctalEscapeSequenceFollowedByDigitCheck.java:60 📄 java-checks/src/main/java/org/sonar/java/checks/OctalEscapeSequenceFollowedByDigitCheck.java:87-89
isAmbiguousFollowUp returns true when an octal escape is followed by \, so a perfectly unambiguous string like "\1\2" (two separate octal escapes) is reported. A backslash unambiguously starts a new escape and is not a digit, which contradicts the rule's intent ("...should not be followed by digits"). Note "\12\3456" is still caught at the second escape (\345 followed by 6) even without this clause, so the backslash case only adds false positives. Remove the || c == '\' branch.

Bug: reportIssue highlights whole literal but test uses precise markers

📄 java-checks/src/main/java/org/sonar/java/checks/OctalEscapeSequenceFollowedByDigitCheck.java:61 📄 java-checks-test-sources/default/src/main/java/checks/OctalEscapeSequenceFollowedByDigitCheckSample.java:5-19
reportIssue(node, ...) raises the issue on the entire literal token (including the surrounding quotes), but the sample file uses precise ^^^ column markers whose positions and widths vary line-to-line and do not span the full literal. Since every literal starts at the same column, whole-node highlighting cannot match these differing markers, so verifyIssues() will fail. Either report a precise sub-range that matches the intended escape, or align the sample markers with the full-literal location.

Edge Case: Text block newline stripping can merge digits across lines

📄 java-checks/src/main/java/org/sonar/java/checks/OctalEscapeSequenceFollowedByDigitCheck.java:42-44
For text blocks the code strips newlines and following whitespace with replaceAll("(\r? |\r)\s*", ""). If an octal escape ends a line and a digit begins the next line, they become adjacent after stripping and produce a false positive even though a real newline separates them in the string. Consider preserving a separator (e.g. replace with a placeholder) so cross-line sequences are not merged.

Edge Case: 3-digit octal parsing ignores \4-\7 two-digit limit

📄 java-checks/src/main/java/org/sonar/java/checks/OctalEscapeSequenceFollowedByDigitCheck.java:82-90 📄 java-checks/src/main/java/org/sonar/java/checks/OctalEscapeSequenceFollowedByDigitCheck.java:67-76
findEscapeEnd always consumes up to 3 octal digits, but Java limits an octal escape whose first digit is 4-7 to two digits (only \0-\3 prefixes allow 3 digits, max \377). So a literal like "\456" is really octal \45 followed by the digit 6 and should be flagged, yet the check consumes '4','5','6' as one escape, pushing escapeEnd to the string end and producing a false negative. This case (first octal digit 4-7 with a third octal digit) is untested by the new max-octal samples. Fix: cap escapeEnd at start+3 (two octal digits) when value.charAt(start+1) is between '4' and '7'.

Implementation Status ◻️ 0 of 1 objectives covered
◻️ SONARJAVA-6826 - 0 of 1 objectives covered

This PR does not implement rule S9359 as the diff is unrelated and focuses on removing Bean Validation annotations.

Other objectives on this issue, possibly covered elsewhere:

  • ◻️ Implement rule S9359: Octal escape sequences should not be followed by digits
Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqube-next

Copy link
Copy Markdown
Contributor

</pre>
<h4>Compliant solution</h4>
<pre data-diff-id="1" data-diff-type="compliant">
String message = "Error code: \n" + "8";

@nathsou nathsou Aug 25, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I find that the concatenation adds noise without improving clarity, but if you prefer the current version, feel free to merge of course.

Suggested change
String message = "Error code: \n" + "8";
String message = "Error code: \n8";

@romainbrenguier
romainbrenguier merged commit 77b8bb0 into master Aug 25, 2026
18 checks passed
@romainbrenguier
romainbrenguier deleted the romain/new-rule-s9359-sonarjava-6826 branch August 25, 2026 14:32
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.

2 participants