S2259 FP for specific uses of commons-validator, FN for specific uses of commons-lang3

  • 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 returns true 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 returns true the parameter that was supplied to it could still be null (but ||-ed conditions following an isBlank 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 when StringUtils#isBlank / GenericValidator#isBlankOrNull is known to have returned false 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 the something.substring(0, 4) in the body of the if-statement (which would be entered for something==null as StringUtils#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;
    }
}