From 8eff7cb917ef783e61122c72624e8750bde8045c Mon Sep 17 00:00:00 2001 From: Romain Brenguier Date: Tue, 25 Aug 2026 11:07:54 +0200 Subject: [PATCH] SONARJAVA-6786: Update S9346 rule metadata and description Improve the rule description with clearer explanations of the Year 2038 problem, code examples, and potential impact. Update JSON metadata to use "Main" scope and reformat for consistency. Co-Authored-By: Claude Opus 4.6 --- .../org/sonar/l10n/java/rules/java/S9346.html | 60 +++++++++++++------ .../org/sonar/l10n/java/rules/java/S9346.json | 23 +++---- 2 files changed, 56 insertions(+), 27 deletions(-) diff --git a/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9346.html b/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9346.html index e052308af3d..13162ad7891 100644 --- a/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9346.html +++ b/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9346.html @@ -1,33 +1,59 @@ -

Using 32-bit signed integer types for timestamps can lead to serious reliability issues such as incorrect time representation, -system failures, and the Year 2038 problem.

+

This is an issue when a smaller integer type value is widened to a larger integer type and then used as an absolute timestamp, such as milliseconds +or seconds since the Unix epoch (January 1, 1970).

Why is this an issue?

-

A 32-bit signed integer can hold values from -2,147,483,648 to 2,147,483,647. While this might seem like a large range, it's insufficient for +

A 32-bit signed integer can hold values from -2,147,483,648 to 2,147,483,647. While this might seem like a large range, it’s insufficient for representing timestamps:

-

When you cast a 32-bit integer to a 64-bit integer for use as a timestamp, you're not fixing the underlying problem — the value is already -corrupted or limited by the 32-bit constraint before the cast happens.

-

Noncompliant code example

+

When you cast a 32-bit integer to a 64-bit integer for use as a timestamp, you’re not fixing the underlying problem — the value is already +corrupted or limited by the 32-bit constraint before the cast happens. The cast simply preserves the incorrect or overflowed value in a larger +container.

+

Timestamps should be stored as 64-bit integer values from the start to ensure they can represent dates far into the past and future without +overflow. A 64-bit integer type can represent timestamps for approximately 292 million years, which is more than sufficient for any practical +application.

+

Using a 32-bit integer for timestamps is almost always a bug that will cause:

+ +

In Java, 32-bit integers are represented by the int type and 64-bit integers by the long type.

+

What is the potential impact?

+

Using 32-bit signed integer types for timestamps can lead to serious reliability issues:

+ +

How to fix it

+

Change the variable type from int to long to properly represent the timestamp. This ensures the value can hold the full +range of possible timestamp values without overflow.

+

Code examples

+

Noncompliant code example

 int timestamp = 1234567890;
-Date date = new Date(timestamp);          // Noncompliant — int implicitly widened
-Date date2 = new Date((long) timestamp);  // Noncompliant — cast doesn't fix overflow
+long epochMillis = (long) timestamp; // Noncompliant
+Date date = new Date(epochMillis);
 
-

Compliant solution

+

Compliant solution

 long timestamp = 1234567890L;
-Date date = new Date(timestamp);
-Date date2 = new Date(timestamp);
+long epochMillis = timestamp;
+Date date = new Date(epochMillis);
 

Resources

Documentation

+ diff --git a/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9346.json b/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9346.json index 094457c0313..5c9521c8715 100644 --- a/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9346.json +++ b/sonar-java-plugin/src/main/resources/org/sonar/l10n/java/rules/java/S9346.json @@ -1,21 +1,24 @@ { "title": "Integer values should not be cast to long for use as timestamps", "type": "BUG", - "code": { - "impacts": { - "RELIABILITY": "HIGH" - }, - "attribute": "LOGICAL" - }, "status": "ready", "remediation": { "func": "Constant\/Issue", - "constantCost": "5min" + "constantCost": "5 min" }, - "tags": ["pitfall", "datetime"], + "tags": [ + "pitfall", + "datetime" + ], "defaultSeverity": "Critical", "ruleSpecification": "RSPEC-9346", "sqKey": "S9346", - "scope": "All", - "quickfix": "unknown" + "scope": "Main", + "quickfix": "unknown", + "code": { + "impacts": { + "RELIABILITY": "HIGH" + }, + "attribute": "LOGICAL" + } }