Standard Analyses

SemmleCode Professional comes with a wide range of pre-packaged analyses, from architectural properties and metrics, to statement-level checks for likely bugs and violations of best practice.


Reference Equality Test on Strings

This query finds code that compares two String objects using == or !=. These operators compare object identity, which may not be intended.

How to Interpret the Query Results

The query flags all occurrences of such an equality test and provides a list of all found occurrences in the results view.

How to Address the Query Results

Usually, non-primitive objects (such as strings) should be compared using their equals methods.

Source Code
import default

/** An expression of type java.lang.String */
class StringValue extends Expr {
  StringValue() {
    this.getType() instanceof TypeString
  }

  predicate isLiteral() {
    this instanceof StringLiteral
  }

  predicate isInterned() {
    // Either this is a call to String.intern()
      exists (Method intern | intern.getDeclaringType() instanceof TypeString and
                              intern.hasName("intern") and
                              ((MethodAccess)this).getMethod() = intern)
   // public static final fields are interned
   or exists (Field f       | f.hasModifier("final") and 
                              f.hasModifier("static") and 
                              f.hasModifier("public") and
                              ((VarAccess)this).getVariable() = f)
   // Deal with parenthesised expressions
   or ((StringValue)((ParExpr)this).getExpr()).isInterned()
  }
}

// VARIATION POINT: The treatment of interned values
// To avoid false positives, and in the hope that people
// who use interned values will know what they're doing,
// it is enough for ONE of the arguments to be interned
// This is highly dubious in the case of public static final
// fields, though.

from EqualityTest e, StringValue lhs, StringValue rhs
where e.getLeftOperand() = lhs
      and e.getRightOperand() = rhs
      and not lhs.isInterned() 
      and not rhs.isInterned()
select e, "String values compared with " + e.getOp()
References