Skip to content

SONARJAVA-6840: Implement S9363: Invalid time-zone IDs should not silently fall back to GMT - #6009

Merged
nathsou merged 2 commits into
masterfrom
new-rule/S9363
Aug 24, 2026
Merged

SONARJAVA-6840: Implement S9363: Invalid time-zone IDs should not silently fall back to GMT#6009
nathsou merged 2 commits into
masterfrom
new-rule/S9363

Conversation

@nathsou

@nathsou nathsou commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Detect invalid compile-time constant IDs passed to TimeZone.getTimeZone(String).
  • Validate named IDs and Java-version-specific custom GMT offsets.
  • Offer deterministic space-to-underscore quick fixes for validated literals.
  • Add focused semantic, no-semantic, Java 18, and Java 19 tests.

Links

AI disclosure

  • LLM model used for implementation: gemini-3.7-flash-high

Detect invalid constant time-zone identifiers before TimeZone silently falls back to GMT, including Java-version-specific custom offset validation and safe literal quick fixes.
@nathsou nathsou self-assigned this Aug 24, 2026
@hashicorp-vault-sonar-prod

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

Copy link
Copy Markdown
Contributor

SONARJAVA-6840

@datadog-sonarsource

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

Ruling needs updating. A fix PR has been created: #6011

Please review and merge it into your branch.

Use the concise digit regex syntax required by S6353 and record the validated S9363 finding produced by the SonarQube server ruling project.
@gitar-bot

gitar-bot Bot commented Aug 24, 2026

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

Implements rule S9363 to detect invalid compile-time constant time-zone IDs in TimeZone.getTimeZone with corresponding quick fixes and test coverage. No issues found.

✅ 2 resolved
Quality: Valid zone IDs depend on analyzer's JDK, not project's JDK

📄 java-checks/src/main/java/org/sonar/java/checks/TimeZoneIdCheck.java:46 📄 java-checks/src/main/java/org/sonar/java/checks/TimeZoneIdCheck.java:93-99
AVAILABLE_ZONE_IDS is built once from TimeZone.getAvailableIDs() of the JVM running the analyzer. The recognized named-ID set varies with JDK/tzdata version, so a project targeting a different JDK may get false positives (a valid target ID flagged) or false negatives. This tradeoff is acknowledged in the rule HTML, so it is minor, but worth confirming it is acceptable and that the analyzer's tzdata is reasonably current.

Bug: test_without_semantic will fail: verifyIssues() with no issues raised

📄 java-checks/src/test/java/org/sonar/java/checks/TimeZoneIdCheckTest.java:52-59
AbstractMethodDetection.visitNode only calls onMethodInvocationFound when matchers().matches(mit) is true, and MethodMatchers.create().ofTypes("java.util.TimeZone") requires the semantic model to resolve the receiver type. With .withoutSemantic() the symbol is unknown, so the matcher never matches and the check raises zero issues. However test_without_semantic runs on TimeZoneIdCheckSample.java (which contains many // Noncompliant expectations) with verifyIssues(), which asserts every expected Noncompliant comment is matched — so this test will fail. Change verifyIssues() to verifyNoIssues() (the established pattern for .withoutSemantic() tests, e.g. FileHeaderCheckTest, DefaultPackageCheckTest).

Implementation Status ✅ 1 / 1 issues implemented
SONARJAVA-6840 — 8 / 8 objectives

The PR successfully implements the S9363 rule with validation, quick fixes, tests, and metadata.

✅ 8 complete
  • ✅ Implement the S9363 rule to detect invalid constant time-zone IDs passed to TimeZone.getTimeZone(String)
  • ✅ Match static java.util.TimeZone.getTimeZone(String) invocations and report issues on the String argument
  • ✅ Add rule metadata and description under the S9363 key
  • ✅ Validate compile-time constant strings against analyzer JVM TimeZone.getAvailableIDs() and custom GMT-offset grammar
  • ✅ Accept custom GMT offsets with seconds only when project Java version is unknown or Java 19 and later
  • ✅ Skip dynamic, unresolved, or non-String values
  • ✅ Offer a quick fix only for uniquely validated string-literal corrections
  • ✅ Add CheckVerifier tests covering IANA IDs, custom GMT offsets, legacy IDs, typos, constants, dynamic values, and quick fixes
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

@github-actions

Copy link
Copy Markdown
Contributor

Ruling Diff Summary

Detected changes in 1 rule files: 0 issues removed, 1 issues added.

S9363 (java) on sonar-server - 0 issues removed, 1 issues added - new ruling file

Added src/test/java/org/sonar/server/issue/index/IssueIndexDebtTest.java (line 75)

(source file not found at this revision: src/test/java/org/sonar/server/issue/index/IssueIndexDebtTest.java)

@sonarqube-next

Copy link
Copy Markdown
Contributor

@gitar-bot

gitar-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown

I checked this directly in InternalCheckVerifier/VisitorsBridgeForTests. withoutSemantic() doesn't fall back to "JDK-only" semantics — it skips enableSemanticWithProjectClasspath(...) entirely, so VisitorsBridgeForTests is built with enableSemantic = false, and createScannerContext then passes Sema model = null to every scanner context (VisitorsBridgeForTests.java:104-105). With no semantic model at all, MethodMatchers.create().ofTypes("java.util.TimeZone") can't resolve the receiver type of TimeZone.getTimeZone(...), so matchers().matches(mit) in AbstractMethodDetection.visitNode never returns true, and the check raises zero issues.

So test_without_semantic calling verifyIssues() against TimeZoneIdCheckSample.java (which has multiple // Noncompliant comments) will fail, since verifyIssues() requires every expected issue to be raised.

Regarding the DateFormatWeekYearCheck comparison: worth double-checking that test too, since if its check is also type-matching based, the same reasoning would apply there. But for this PR, the fix is to change verifyIssues() to verifyNoIssues() in test_without_semantic here.

@nathsou
nathsou merged commit 4d096b0 into master Aug 24, 2026
23 checks passed
@nathsou
nathsou deleted the new-rule/S9363 branch August 24, 2026 13:54
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