Skip to content

SONARJAVA-6786 Implement new rule S9346: Integer values should not be cast to long for use as timestamps - #5957

Open
romainbrenguier wants to merge 4 commits into
masterfrom
new-rule/SONARJAVA-6786-S9346
Open

SONARJAVA-6786 Implement new rule S9346: Integer values should not be cast to long for use as timestamps#5957
romainbrenguier wants to merge 4 commits into
masterfrom
new-rule/SONARJAVA-6786-S9346

Conversation

@romainbrenguier

Copy link
Copy Markdown
Contributor

Detect 32-bit or smaller integer values (int, short, byte, char) passed as arguments to timestamp-consuming APIs (Date, Timestamp, Instant, Calendar), where the narrow type causes overflow or data corruption.

Detect 32-bit or smaller integer values (int, short, byte, char) passed
as arguments to timestamp-consuming APIs (Date, Timestamp, Instant,
Calendar), where the narrow type causes overflow or data corruption.
@hashicorp-vault-sonar-prod

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

Copy link
Copy Markdown
Contributor

SONARJAVA-6786

Comment on lines +80 to +92
private void checkArgument(ExpressionTree argument) {
ExpressionTree arg = ExpressionUtils.skipParentheses(argument);
if (arg.is(Tree.Kind.TYPE_CAST)) {
arg = ((TypeCastTree) arg).expression();
}
Type type = arg.symbolType();
if (type.isUnknown()) {
return;
}
if (isNarrowIntegerType(type)) {
reportIssue(argument, MESSAGE);
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Bug: Rule misses documented case: int cast stored in long variable

The canonical Noncompliant example in S9346.html stores (long) timestamp in a long variable and then passes that variable to new Date(epochMillis). The implementation's checkArgument only inspects the direct argument at the call site (skipping parentheses and unwrapping a single TypeCast), so a long-typed variable argument yields a non-narrow type and is never reported. The primary documented pattern is therefore a false negative and is not covered by the sample test file. Either narrow the documentation example to match what the check detects (cast/int directly in the call), or extend the check to trace the argument's initializer when it is a local variable assigned from a narrow-int cast, and add a corresponding test case.

Was this helpful? React with 👍 / 👎

@github-actions

Copy link
Copy Markdown
Contributor

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

Please review and merge it into your branch.

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

Ruling Diff Summary

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

S9346 (java) on eclipse-jetty - 0 issues removed, 2 issues added - new ruling file

Added jetty-util-ajax/src/test/java/org/eclipse/jetty/util/ajax/JSONTest.java (line 366)

(source file not found at this revision: jetty-util-ajax/src/test/java/org/eclipse/jetty/util/ajax/JSONTest.java)

Added jetty-util-ajax/src/test/java/org/eclipse/jetty/util/ajax/JSONTest.java (line 433)

(source file not found at this revision: jetty-util-ajax/src/test/java/org/eclipse/jetty/util/ajax/JSONTest.java)

romainbrenguier and others added 2 commits August 19, 2026 14:07
- Fix secondary location marker alignment in test sample (off by one space)
- Exclude int literal arguments (e.g., `new Date(0)`) from detection to
  reduce false positives on intentional small values
- Update HTML noncompliant example to show patterns the rule actually
  detects (direct int arg and explicit cast) instead of the variable
  indirection pattern which is not detected

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The previous commit excluded int literals from S9346, which means
the eclipse-jetty findings at JSONTest.java lines 366 and 433 are
no longer raised.

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

gitar-bot Bot commented Aug 19, 2026

Copy link
Copy Markdown
Code Review ⚠️ Changes requested 1 resolved / 2 findings

Implements new SonarJava rule S9346 to detect narrow integer values passed to timestamp APIs, but the implementation misses the documented canonical case where an int cast is stored in a long variable.

⚠️ Bug: Rule misses documented case: int cast stored in long variable

📄 java-checks/src/main/java/org/sonar/java/checks/IntegerToLongTimestampCastCheck.java:80-92 📄 sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9346.html:14-18

The canonical Noncompliant example in S9346.html stores (long) timestamp in a long variable and then passes that variable to new Date(epochMillis). The implementation's checkArgument only inspects the direct argument at the call site (skipping parentheses and unwrapping a single TypeCast), so a long-typed variable argument yields a non-narrow type and is never reported. The primary documented pattern is therefore a false negative and is not covered by the sample test file. Either narrow the documentation example to match what the check detects (cast/int directly in the call), or extend the check to trace the argument's initializer when it is a local variable assigned from a narrow-int cast, and add a corresponding test case.

✅ 1 resolved
Edge Case: Rule flags legitimate int/long-literal timestamps causing noise

📄 java-checks/src/main/java/org/sonar/java/checks/IntegerToLongTimestampCastCheck.java:80-94 📄 java-checks-test-sources/default/src/main/java/checks/IntegerToLongTimestampCastCheckSample.java:75-77
The check reports any narrow-int argument including plain literals such as new Date(0) and int constants that represent valid timestamps within the int range (e.g. seconds fitting before 2038). In real codebases new Date(0) (epoch) and small constants are common and intentional, so this may generate a high volume of false positives. Consider excluding constant/literal arguments or those provably within a safe range, or documenting this behavior explicitly in the RSPEC.

🤖 Prompt for agents
Code Review: Implements new SonarJava rule S9346 to detect narrow integer values passed to timestamp APIs, but the implementation misses the documented canonical case where an int cast is stored in a long variable.

1. ⚠️ Bug: Rule misses documented case: int cast stored in long variable
   Files: java-checks/src/main/java/org/sonar/java/checks/IntegerToLongTimestampCastCheck.java:80-92, sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9346.html:14-18

   The canonical Noncompliant example in S9346.html stores `(long) timestamp` in a `long` variable and then passes that variable to `new Date(epochMillis)`. The implementation's `checkArgument` only inspects the direct argument at the call site (skipping parentheses and unwrapping a single TypeCast), so a `long`-typed variable argument yields a non-narrow type and is never reported. The primary documented pattern is therefore a false negative and is not covered by the sample test file. Either narrow the documentation example to match what the check detects (cast/int directly in the call), or extend the check to trace the argument's initializer when it is a local variable assigned from a narrow-int cast, and add a corresponding test case.

Implementation Status ✅ 1 / 1 issues implemented
SONARJAVA-6786 — 1 / 1 objectives

The PR successfully implements rule S9346 (Integer values should not be cast to long for use as timestamps) with appropriate check logic, tests, metadata, and documentation.

✅ 1 complete
  • ✅ Implement new rule S9346: Integer values should not be cast to long for use as timestamps
Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.
Unblock → Override a blocking verdict and allow merging.

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

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

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqube-next

Copy link
Copy Markdown
Contributor

@romainbrenguier
romainbrenguier marked this pull request as ready for review August 20, 2026 13:42
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.

1 participant