@SomeAnnotation(name = value)
package javax.annotation;
import java.text.ParseException;
import java.util.List;
@interface CheckForNull {}
@interface Nonnull {}
@interface Nullable {}
class NullPointerTest {
// tests constructs that can generate an issue. namely, syntax constructs that performs a potential null dereference.
public void testIssues() {
//Not tested right away : those are invalid construction anyway.
// null[0]; // {{null is dereferenced}}
// null.field; // {{null is dereferenced}}
// null.method(); // {{null is dereferenced}}
}
public Object[] field;
public Object[] method() {
return null;
}
@Nonnull
public Object[] notnullableField;
@Nonnull
public Object[] notnullableMethod() {
return null;
}
@CheckForNull
public Object[] checkForNullField;
@CheckForNull
public Object[] checkForNullMethod() {
return null;
}
@Nullable
public Object[] nullableField;
@Nullable
public Object[] nullableMethod() {
return nullableField;
}
public void testNotnullable(Object[] parameter) {
int i;
Object o;
Object[] array1 = notnullableField;
i = array1.length; // No issue
i = notnullableField.length; // No issue
Object[] array2 = notnullableMethod();
i = array2.length; // No issue
i = notnullableMethod().length; // No issue
parameter.hashCode();
}
public void testCheckNotNull(@CheckForNull Object parameter) {
int i;
Object o;
Object[] array1 = checkForNullField;
i = array1.length; // False negative
i = checkForNullField.length; // False negative, instance and static fields are not checked
Object[] array2 = checkForNullMethod(); // flow@array {{...}} flow@array {{array2 is assigned null}}
i = array2.length; // Noncompliant [[flows=array]] {{NullPointerException might be thrown as 'array2' is nullable here}} flow@array
}
public void testCheckNotNull(@CheckForNull Object parameter) {
int i;
i = checkForNullMethod().length; // Noncompliant {{NullPointerException might be thrown as 'checkForNullMethod' is nullable here}}
}
public void testNullable(@Nullable Object parameter) {
int i;
Object o;
Object[] array1 = nullableField;
if (array1.length != 0) { } // False negative
i = nullableField.length; // False negative, instance and static fields are not checked
Object[] array2 = nullableMethod();
i = array2.length; // Compliant
i = nullableMethod().length; // Compliant
}
public class A {
@DummyAnnotation
Object a;
@CheckForNull
Object b;
@Nullable
Object c;
}
public void testMemberSelect(A a1, @CheckForNull A a2, @Nullable A a3) {
a1.hashCode(); // No issue
a2.hashCode(); // Noncompliant {{NullPointerException might be thrown as 'a2' is nullable here}}
a3.hashCode(); // Noncompliant {{NullPointerException might be thrown as 'a3' is nullable here}}
a1.a.hashCode(); // No issue
a1.b.hashCode(); // False negative
a1.c.hashCode(); // False negative
}
public void method1(@Nullable Object[] a1, @Nullable Object... variadic) {
}
public void method2(@Nonnull Object[] a1, @Nonnull Object... variadic) {
}
public void testMethodInvocation() {
method1(notnullableField, // No issue
notnullableField, // No issue
notnullableField); // No issue
method2(notnullableField, // No issue
notnullableField, // No issue
notnullableField); // No issue
method1(checkForNullField, // No issue
checkForNullField, // No issue
checkForNullField); // No issue
method2(checkForNullField, // False negative, instance and static fields are not checked
checkForNullField, // False negative, instance and static fields are not checked
checkForNullField); // False negative, instance and static fields are not checked
method1(notnullableMethod(), // No issue
notnullableMethod(), // No issue
notnullableMethod()); // No issue
method2(notnullableMethod(), // No issue
notnullableMethod(), // No issue
notnullableMethod()); // No issue
method1(checkForNullMethod(), // No issue
checkForNullMethod(), // No issue
checkForNullMethod()); // No issue
// method2(checkForNullMethod(), // false negative Noncompliant {{'checkForNullMethod' is nullable here and method 'method2' does not accept nullable argument}}
// checkForNullMethod(), // false negative Noncompliant {{'checkForNullMethod' is nullable here and method 'method2' does not accept nullable argument}}
// checkForNullMethod()); // false negative Noncompliant {{'checkForNullMethod' is nullable here and method 'method2' does not accept nullable argument}}
method1(null, // No issue
null, // No issue
null); // No issue
// method2(null, // false negative Noncompliant {{method 'method2' does not accept nullable argument}}
// null, // false negative Noncompliant {{method 'method2' does not accept nullable argument}}
// null); // false negative Noncompliant {{method 'method2' does not accept nullable argument}}
}
public void testIf(Object argument1) {
argument1.hashCode(); // Compliant
}
public void testIf(Object argument1, Object argument2, Object argument3) {
if (argument1 == null) {
argument1.hashCode(); // Noncompliant {{NullPointerException might be thrown as 'argument1' is nullable here}}
argument1 = argument3;
argument1.hashCode(); // Compliant
} else {
argument1.hashCode(); // Compliant
argument1 = null;
argument1.hashCode(); // Noncompliant {{NullPointerException might be thrown as 'argument1' is nullable here}}
}
argument1.hashCode(); // Compliant
argument2.hashCode(); // Compliant
}
public void testIf2(Object argument1, Object argument2, Object argument3) {
if (null != argument2) {
argument2.hashCode(); // Compliant
argument2 = null;
argument2.hashCode(); // Noncompliant {{NullPointerException might be thrown as 'argument2' is nullable here}}
} else {
argument2.hashCode(); // Noncompliant {{NullPointerException might be thrown as 'argument2' is nullable here}}
argument2 = argument3;
argument2.hashCode(); // Compliant
}
argument2.hashCode(); // Compliant
}
public void testIfMerge1(Object argument1, Object argument2, Object argument3, Object argument4, boolean condition) {
if (argument1 == null) {
argument1 = new Object();
} else {
}
argument1.hashCode(); // Compliant
if (null != argument2) {
} else {
argument2 = new Object();
}
argument2.hashCode(); // Compliant
if (condition) {
argument4 = null;
} else {
argument4 = null;
}
argument4.hashCode(); // Noncompliant {{NullPointerException might be thrown as 'argument4' is nullable here}}
}
public void testIfMerge2(Object argument1, Object argument2, Object argument3, Object argument4, boolean condition) {
if (argument3 == null) {
if (condition) {
argument3 = new Object();
} else {
argument3 = new Object();
}
argument3.hashCode(); // Compliant
}
argument3.hashCode(); // Compliant
}
public void testConditional(Object argument1, Object argument2, Object argument3, Object argument4) {
int result1 = argument1 == null ? 0 : argument1.hashCode(); // Compliant
argument1.hashCode(); // Noncompliant
int result2 = argument2 == null ? argument2.hashCode() : 0; // Noncompliant {{NullPointerException might be thrown as 'argument2' is nullable here}}
argument2.hashCode(); // Compliant
int result3 = argument3 != null ? 0 : argument3.hashCode(); // Noncompliant {{NullPointerException might be thrown as 'argument3' is nullable here}}
argument3.hashCode(); // Compliant
int result4 = argument4 != null ? argument4.hashCode() : 0; // Compliant
argument4.hashCode(); // Noncompliant
}
public void testCondition() {
String var1 = null;
if (var1.equals("")) { } // Noncompliant {{NullPointerException might be thrown as 'var1' is nullable here}}
String var2 = nullableMethod();
if (var2.equals("")) { } // Compliant
}
public void testTry() {
Object object = null;
try {
object = new Object();
} catch (Exception e) {
object.hashCode(); // Noncompliant
} finally {
object.hashCode();// Noncompliant
}
Object object2;
try{
object2 = potentiallyRaiseException();
} finally {
System.out.println("foo");
}
object2.toString(); // not accessible with null value
}
public void testLogicalAnd(String str, Object object) {
if (object != null && object.hashCode() == 0) ; // Compliant
if (object != null && object.hashCode() != 0 && object.hashCode() != 0) ; // Compliant
if (object == null && object.hashCode() == 0) ; // Noncompliant {{NullPointerException might be thrown as 'object' is nullable here}}
}
public void testLogicalAnd2(String str, Object object) {
if (object == null && object.hashCode() == 0 && object.hashCode() == 0); // Noncompliant {{NullPointerException might be thrown as 'object' is nullable here}}
}
public void testLogicalAnd3(String str) {
boolean b2 = str != null && str.length() == 0; // Compliant
boolean b1 = str == null && str.length() == 0; // Noncompliant {{NullPointerException might be thrown as 'str' is nullable here}}
}
public void testLogicalOr(String str, Object object) {
if (object == null || object.hashCode() == 0) ; // Compliant
if (object == null || object.hashCode() != 0 || object.hashCode() != 0) ; // Compliant
if (object != null || object.hashCode() == 0) ; // Noncompliant {{NullPointerException might be thrown as 'object' is nullable here}}
}
public void testLogicalOr2(String str, Object object) {
if (object != null || object.hashCode() == 0 || object.hashCode() == 0) ; // Noncompliant {{NullPointerException might be thrown as 'object' is nullable here}}
boolean b1 = str == null || str.length() == 0; // Compliant
}
public void testLogicalOr3(String str) {
boolean b2 = str != null || str.length() == 0; // Noncompliant {{NullPointerException might be thrown as 'str' is nullable here}}
}
public void testDoWhileLoop(boolean condition) {
Object object1 = null, object2 = null, object3 = null;
do {
object1.hashCode(); // Noncompliant {{NullPointerException might be thrown as 'object1' is nullable here}}
if (condition) {
object2 = new Object();
}
object1 = null;
object3 = new Object();
} while (object1.hashCode()); //issue already raised
}
public void testDoWhileLoop2(boolean condition) {
Object object1 = new Object(), object2 = null, object3 = null;
do {
object1.hashCode();
if (condition) {
object2 = new Object();
}
object1 = null;
object3 = new Object();
} while (object1.hashCode() < 0); // Noncompliant {{NullPointerException might be thrown as 'object1' is nullable here}}
object1.hashCode(); // issue already raised
object2.hashCode(); // Compliant
object3.hashCode(); // Compliant
}
public void testForLoop() {
Object object = null;
for (; object.hashCode() != 0; object.hashCode()) { // Noncompliant {{NullPointerException might be thrown as 'object' is nullable here}}
object.hashCode();
object = null;
}
}
public void testForLoop2() {
for(Object object1 = null, object2 = null; true; object2.hashCode()) {
object1.hashCode(); // Noncompliant {{NullPointerException might be thrown as 'object1' is nullable here}}
}
}
public void testForEachLoop() {
Object value;
Set<Object> set = null;
Entry head = null;
for(Object entry : set.values()) { // Noncompliant {{NullPointerException might be thrown as 'set' is nullable here}}
//all potential npe after this one are not raised as symbolic execution is cut.
head.hashCode();
value = null;
value.hashCode();
}
head.hashCode();
value.hashCode();
}
public void testForEachLoopGood() {
List<String> foos = collectFoos();
for (String foo : foos) {
foo.toString();
}
}
public void testPrimitiveForEachLoopGood() {
boolean[] foos = collectFoos();
for (boolean foo : foos) {
if (foo) {
println("true");
}
}
}
public static int testPrimitiveForEachLoopGuava(boolean... values) {
int count = 0;
for (boolean value : values) {
if (value) {
count++;
}
}
return count;
}
private Object a = null;
public void newInstance() {
if (a == null) {
testPrimitiveForEachLoopGood();
}
a.toString();
}
protected Constructor constructor = null;
public void newInstanceBis() throws IllegalAccessException, InstantiationException {
if (constructor == null) {
this.setDynaBeanClass();
}
return ((DynaBean) constructor.newInstance(constructorValues));
}
public void testWhileLoop() {
Object object1 = null, object2 = new Object();
while(object1.hashCode() > 0) { // Noncompliant {{NullPointerException might be thrown as 'object1' is nullable here}}
object2.hashCode(); // Compliant, issue already raised
}
object1.hashCode(); // Compliant, issue already raised
object2.hashCode(); // Compliant
}
public void testWhileLoop() {
Object object1 = new Object(), object2 = null, object3 = null;
while(object1.hashCode() > 0) { // compliant
object2.hashCode(); // Noncompliant
}
object1.hashCode(); // Compliant, issue already raised
//(if condition of while is false, we might end up here with object2 null)
object2.hashCode(); // Noncompliant
}
public void testHoistedLoop(boolean condition) {
Object a = null;
while(condition) {
a.hashCode(); // Noncompliant
a = null;
}
a.hashCode(); // Noncompliant
}
public void testInstanceField() {
nullableField = null;
nullableField.hashCode(); // Noncompliant
}
public void testSwitch() {
String str1 = null, str2 = "", str3 = "";
switch(str1) { // Noncompliant {{NullPointerException might be thrown as 'str1' is nullable here}}
case "ONE":
str2.length();
}
str3.length();
}
public void testSwitch2() {
String str1 = "", str2 = null, str3 = "";
switch(str1) {
case "ONE":
str2.length(); // Noncompliant {{NullPointerException might be thrown as 'str2' is nullable here}}
}
str3.length();
}
public void testSwitch3() {
String str1 = "", str2 = "", str3 = null;
switch(str1) {
case "ONE":
str2.length();
}
str3.length(); // Noncompliant {{NullPointerException might be thrown as 'str3' is nullable here}}
}
public void testMergeOnParameter(@CheckForNull Object o) {
if(o != null) {
return;
}
o.toString(); // Noncompliant
}
public void testMergeOnParameter(@Nullable Object o) {
if(o == null) {
return;
}
o.hashCode(); // Compliant, constraint is lost
Object a = o;
a.hashCode(); // Compliant
}
public void testAssignNullableMethod() {
Object object;
object = nullableMethod();
if(object.hashCode()) { } // Compliant
object = null;
if(object.hashCode()) { } // Noncompliant {{NullPointerException might be thrown as 'object' is nullable here}}
}
public void testComplexLoop(@Nullable Object nullableObject) {
Object object1 = null, object11 = null, object12 = null;
for (int i = 0; object11 == null; i += 1) {
object11.hashCode(); // Noncompliant {{NullPointerException might be thrown as 'object11' is nullable here}}
object12.hashCode();
nullableObject.hashCode();
if (i == 1) {
object1.hashCode(); // Compliant
} else if (i == 0) {
object1 = new Object();
}
object11 = null;
}
object1.hashCode(); // Compliant not executed because loop is always executed at least once and raising NPE
}
public void testComplexLoop2(@Nullable Object nullableObject) {
Object object2 = null, object21 = null, object22 = null;
int i = 0;
while(object21 == null) {
object21.hashCode(); // Noncompliant {{NullPointerException might be thrown as 'object21' is nullable here}}
object22.hashCode(); // no issue, as npe is thrown on previous line
nullableObject.hashCode();
if(i == 1) {
object2.hashCode(); // Compliant
} else if(i == 0) {
object2 = new Object();
}
object21 = null;
}
object2.hashCode();
Object object3 = null;
int j = 0;
do {
if(j == 1) {
object3.hashCode(); // False negative
} else if(j == 0) {
object3 = new Object();
}
} while (condition);
object3.hashCode(); // False negative
}
void testComplexSwitch(String str) {
Object object1 = null, object2 = null, object3 = null, object4 = new Object();
switch(str) {
case "ONE":
object1 = new Object();
break;
case "TWO":
object1.hashCode(); // Noncompliant
break;
case "THREE":
object2 = new Object();
case "FOUR":
object2.hashCode(); // Noncompliant
break;
case "FIVE":
object3.hashCode(); // Noncompliant {{NullPointerException might be thrown as 'object3' is nullable here}}
object4 = null;
case "SIX":
object4.hashCode(); // False negative
}
}
public static class LinkedListEntry {
@Nullable
LinkedList parent() {
return null;
}
}
public void testAssignSelfMember() {
LinkedListEntry entry2;
entry2 = entry2.parent(); // Noncompliant
}
@interface CoverageAnnotation {
}
@CoverageAnnotation // Coverage
public Object coverageMethod() { // Coverage
return new Object();
}
public void testCoverage(Object[] a) {
coverageMethod().hashCode(); // Coverage
invalidMethod(); // Coverage
if (0) { } // Coverage
if (0 == 0) { } // Coverage
a[0] = null; // Coverage
if (null == coverageMethod()) { } // Coverage
if (a == null) { } // Coverage
if (a != null) { } // Coverage
undefined.field; // Coverage
a = 1 + 2; // Coverage
}
static int a1;
static {
a1 = 0;
}
public void hasNullableParameters(String a, @Nullable String b) {
a.length();
b.length(); // Noncompliant {{NullPointerException might be thrown as 'b' is nullable here}}
}
public void test(@CheckForNull A a, @CheckForNull A b) {
a.hashCode(); // Noncompliant
b.hashCode(); // Noncompliant
}
public boolean indirectNull(CharSequence s1, CharSequence s2) {
int length = s1.length();
if (s1 == s2) {
return true;
}
if (length != s2.length()) {
return false;
}
return true;
}
void foo(Object qix, @Nullable Object bar) {
foo(bar, NullPointerTest.class);
}
public void maybePropagateCancellation(@Nullable Object related) {
if (related != null & isCancelled()) {
related.toString();
}
}
void while_loop() {
Object currentParent = new Object();
while (currentParent != null) {
printState();
currentParent.toString();
currentParent = null;
}
}
@Override
public boolean equals(Object obj) {
return getValue() == ((MyClass) obj).getValue(); // Noncompliant {{NullPointerException might be thrown as 'obj' is nullable here}}
}
private void equalsToCheckForNull(Integer a) {
Objeect b = checkForNullMethod();
if (a.equals(b)) {
System.out.println("Found!");
}
a.toString(); // Compliant: a cannot be null hereafter
this.checkForNullMethod().toString(); // Noncompliant {{NullPointerException might be thrown as 'checkForNullMethod' is nullable here}}
}
@Nonnull
public static String getNonNullString() {
return "Rachmaninov";
}
public static void useNonNullString() {
String nonNullString = getNonNullString();
if (nonNullString != null) {
System.out.println(nonNullString);
}
int n = nonNullString.length(); // Compliant!
}
Object parseNullException(String object) throws Exception {
Object result = null;
Exception ex = null;
try {
result = parseObject(object);
} catch (ParseException e) {
ex = e;
}
if (result == null) {
throw ex; // Noncompliant {{NullPointerException might be thrown as 'ex' is nullable here}}
}
return result;
}
private void bar(@Nullable Object v) {
NullPointerTest.qix(v, v != null ? "A" : null); // Compliant
NullPointerTest.qix(v, (v != null && "B".equals(v.toString())) ? "B" : null); // Compliant
NullPointerTest.qix(v, (v == null || "B".equals(v.toString())) ? "B" : null); // Compliant
}
static void qix(Object o1, Object o2) { }
private static boolean testSomething1(List<String> p1, @Nullable String p2) {
return p1.isEmpty() && p2 != null && p2.length() > 0 && p2.charAt(0) == '?';
}
private static boolean testSomething2(List<String> p1, @Nullable String p2) {
return p1.isEmpty() || p2 == null || p2.length() > 0 || p2.charAt(0) == '?';
}
public boolean checkThatStuff(@Nullable Object c) {
return checkSomething("HELLO") && c instanceof MyClass && ((MyClass) c).isLike("hello");
}
private static boolean checkSomething(String s) {
return s.isEmpty();
}
}
class MyClass {
private MyClass(ThreadGroup tg) {
java.security.AccessController.doPrivileged(
(java.security.PrivilegedAction<Void>) () -> {
final Thread hook = new Thread(
tg,
new Runnable() {
@Override
public void run() {
unknownMethod(); // owner of the corresponding unknown symbol is PackageSymbol, with type null
}
},
"threadName");
return null;
});
}
boolean isLike(String s) {
return s.isEmpty();
}
}
class RaisedExceptionCannotBeNull {
void foo() {
try {
Thread.sleep(0);
} catch (Exception ex) {
for (Throwable cause = ex; cause != null; cause = cause.getCause()) { // assigned to cause then tested agains null...
// do something
}
ex.getCause(); // FP on squid:S2259 as it might have been null or not because of the for loop condition
}
}
}
class FooBar {
private static void foo(Object o, boolean b) {
FooBar.foo(null, true); // Compliant
}
private static void bar(Object o, byte[] b) {
FooBar.bar(null, new byte[10]); // Compliant
}
}