-
What language is this for?
- Java
-
Which rule?
- S2259 (Null pointers should not be dereferenced)
-
Why do you believe it’s a false-positive/false-negative?
If
org.apache.commons.validator.GenericValidator#isBlankOrNull
returnstrue
for a variable then it is known that an||
-ed condition will be short-circuited when a nullable variable is null. Therefor a NullPointerException cannot be thrown for later clauses of the||
-ed condition for which SQ currently flags the potential NPE.If
org.apache.commons.lang3.StringUtils#isBlank
returnstrue
the parameter that was supplied to it could still be null (but||
-ed conditions following anisBlank
on a null-value will be short-circuited)For both cases a return-value of
false
from the method is a guarantee that the parameter supplied was non-null, so for both cases code that is only executed whenStringUtils#isBlank
/GenericValidator#isBlankOrNull
is known to have returnedfalse
for a variable can safely assume that variable is non-null without further checks. -
Are you using
- SonarQube Server / Community Build - Community Build v25.4.0.105899
- SonarQube for IDE - IntelliJ IDEA 10.27.1.81796 on IDEA Ultimate 2025.1.3
-
How can we reproduce the problem?
-
Create a project with the apache commons-lang3 (3.18.0) and commons-validator (1.10.0) libraries
-
Observe that in the conditions of the if-statement where commons-validator GenericValidator#isBlankOrNull check is preceding the java.lang.String#length() call SQ is falsely raising FP S2259 as the condition would be short-circuited by isBlankOrNull returning true for null-values
-
Observe that for the if-block with
StringUtils#isBlank
in the conditions SQ is subject to a FN for S2259 for thesomething.substring(0, 4)
in the body of the if-statement (which would be entered forsomething==null
asStringUtils#isBlank
will return true in that case).
-
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.validator.GenericValidator;
import java.util.Random;
public class S2259FP_CommonsValidator_isBlankOrNull
{
private static final Random RANDOM = new Random();
public static String nullableGet() {
if (RANDOM.nextBoolean()) {
return null;
}
return "S2259FalsePositives";
}
public static String S2259( String[] args )
{
String something = S2259FP_CommonsValidator_isBlankOrNull.nullableGet();
String result="";
// Falsely flags something.length() NPE sensitive as the condition evaluation short-circuits
// on isBlankOrNull returning true for null-values
// Correctly flags something.substring(0, 4) NPE sensitive
// as isBlankOrNull will return true for null-values
if (GenericValidator.isBlankOrNull(something) || something.length() >= 4) {
result = something.substring(0, 4);
}
// Correctly considers something.length() not NPE sensitive as the condition evaluation
// short-circuits on isBlank returning true for null-values
// Falsely does not flag something.substring(0, 4) as NPE sensitive
// as isBlank will return true for null-values
if (StringUtils.isBlank(something) || something.length() >= 4) {
result = something.substring(0, 4);
}
return result;
}
}