Issue:
Rule S2259 (Null pointers should not be dereferenced) fails to detect null pointer dereferences when the null check is performed using instanceof instead of an explicit != null comparison.
Code to reproduce:
class Foo {
private void foo1(String s1) {
if (s1 != null) return;
String str = s1.toString(); // S2259 reported ✓
}
private void foo2(String s2) {
if (s2 instanceof String) return;
String str = s2.toString(); // S2259 NOT reported ✗
}
}
Expected behavior:
Both foo1() and foo2() should be reported with S2259, since both methods dereference a variable that is guaranteed to be null on some execution path.
Actual behavior:
SonarQube scan results:
[MAJOR] java:S2259: A "NullPointerException" could be thrown; "s1" is nullable here. at line 4
// Line 9 (foo2): NO S2259 report
[MAJOR] java:S1144: Remove this unused private "foo2" method. at line 7
[MINOR] java:S1481: Remove this unused "str" local variable. at line 9
[MINOR] java:S1858: "s2" is already a string, there's no need to call "toString()" on it. at line 9
Only foo1() is reported with S2259. foo2() is silently ignored.
Analysis:
When a variable x with static type T is checked using x instanceof T, this is semantically equivalent to a null check, since instanceof returns false for null values:
// When x has static type T:
x instanceof T ≡ x != null
Runtime verification:
Both methods throw NullPointerException when passed null:
public class Test {
public static void main(String[] args) {
try { new Foo().foo1(null); }
catch (NullPointerException e) { System.out.println("foo1 NPE!"); }
try { new Foo().foo2(null); }
catch (NullPointerException e) { System.out.println("foo2 NPE!"); }
}
}
Output:
foo1 NPE!
foo2 NPE!
Versions:
- SonarQube Server: 26.1.0.118079 Community Build
- Scanner: SonarScanner CLI 8.0.1.6346
- Java Plugin: 8.22.0.41895
- Java version: JDK 21
Deployment:
Deployed as a standalone server