mirror of
https://github.com/github/codeql.git
synced 2026-04-26 17:25:19 +02:00
Use EqualityTest for either value or ref comparions, and ReferenceEqualityTest for strictly ref comparison.
This commit is contained in:
committed by
Ian Lynagh
parent
f95effcf82
commit
7dec3f4835
@@ -9,6 +9,6 @@
|
||||
|
||||
import java
|
||||
|
||||
from AnyEqualityTest eq
|
||||
from EqualityTest eq
|
||||
where eq.getAnOperand() instanceof BooleanLiteral
|
||||
select eq
|
||||
|
||||
@@ -1099,8 +1099,8 @@ class GreaterThanComparison extends ComparisonExpr {
|
||||
*
|
||||
* This could be a reference- or a value-in/equality test.
|
||||
*/
|
||||
class AnyEqualityTest extends BinaryExpr {
|
||||
AnyEqualityTest() {
|
||||
class EqualityTest extends BinaryExpr {
|
||||
EqualityTest() {
|
||||
this instanceof EQExpr or
|
||||
this instanceof NEExpr or
|
||||
this instanceof ValueEQExpr or
|
||||
@@ -1121,12 +1121,12 @@ class AnyEqualityTest extends BinaryExpr {
|
||||
|
||||
/**
|
||||
* An equality test is a binary expression using
|
||||
* Java's `==` or `!=` operator.
|
||||
* Java's `==` or `!=` operators or Kotlin's `===` or `!==` operators.
|
||||
*
|
||||
* If either operand is a reference type, this is a reference-in/equality test.
|
||||
*/
|
||||
class EqualityTest extends AnyEqualityTest {
|
||||
EqualityTest() {
|
||||
class ReferenceEqualityTest extends EqualityTest {
|
||||
ReferenceEqualityTest() {
|
||||
this instanceof EQExpr or
|
||||
this instanceof NEExpr
|
||||
}
|
||||
|
||||
@@ -242,7 +242,7 @@ private predicate guardControls_v3(Guard guard, BasicBlock controlled, boolean b
|
||||
}
|
||||
|
||||
private predicate equalityGuard(Guard g, Expr e1, Expr e2, boolean polarity) {
|
||||
exists(AnyEqualityTest eqtest |
|
||||
exists(EqualityTest eqtest |
|
||||
eqtest = g and
|
||||
polarity = eqtest.polarity() and
|
||||
eqtest.hasOperands(e1, e2)
|
||||
|
||||
@@ -35,7 +35,7 @@ predicate implies_v1(Guard g1, boolean b1, Guard g2, boolean b2) {
|
||||
b1 = b2.booleanNot() and
|
||||
b1 = [true, false]
|
||||
or
|
||||
exists(AnyEqualityTest eqtest, boolean polarity, BooleanLiteral boollit |
|
||||
exists(EqualityTest eqtest, boolean polarity, BooleanLiteral boollit |
|
||||
eqtest = g1 and
|
||||
eqtest.hasOperands(g2, boollit) and
|
||||
eqtest.polarity() = polarity and
|
||||
|
||||
@@ -42,7 +42,7 @@ class IntComparableExpr extends Expr {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
Expr integerGuard(IntComparableExpr e, boolean branch, int k, boolean is_k) {
|
||||
exists(AnyEqualityTest eqtest, boolean polarity |
|
||||
exists(EqualityTest eqtest, boolean polarity |
|
||||
eqtest = result and
|
||||
eqtest.hasOperands(e, any(ConstantIntegerExpr c | c.getIntValue() = k)) and
|
||||
polarity = eqtest.polarity() and
|
||||
@@ -53,7 +53,7 @@ Expr integerGuard(IntComparableExpr e, boolean branch, int k, boolean is_k) {
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(AnyEqualityTest eqtest, int val, Expr c, boolean upper |
|
||||
exists(EqualityTest eqtest, int val, Expr c, boolean upper |
|
||||
k = e.relevantInt() and
|
||||
eqtest = result and
|
||||
eqtest.hasOperands(e, c) and
|
||||
|
||||
@@ -17,7 +17,7 @@ Expr alwaysNullExpr() {
|
||||
|
||||
/** Gets an equality test between an expression `e` and an enum constant `c`. */
|
||||
Expr enumConstEquality(Expr e, boolean polarity, EnumConstant c) {
|
||||
exists(AnyEqualityTest eqtest |
|
||||
exists(EqualityTest eqtest |
|
||||
eqtest = result and
|
||||
eqtest.hasOperands(e, c.getAnAccess()) and
|
||||
polarity = eqtest.polarity()
|
||||
@@ -36,7 +36,7 @@ InstanceOfExpr instanceofExpr(SsaVariable v, RefType type) {
|
||||
*
|
||||
* Note this includes Kotlin's `==` and `!=` operators, which are value-equality tests.
|
||||
*/
|
||||
AnyEqualityTest varEqualityTestExpr(SsaVariable v1, SsaVariable v2, boolean isEqualExpr) {
|
||||
EqualityTest varEqualityTestExpr(SsaVariable v1, SsaVariable v2, boolean isEqualExpr) {
|
||||
result.hasOperands(v1.getAUse(), v2.getAUse()) and
|
||||
isEqualExpr = result.polarity()
|
||||
}
|
||||
@@ -174,7 +174,7 @@ predicate nullCheckMethod(Method m, boolean branch, boolean isnull) {
|
||||
* is true, and non-null if `isnull` is false.
|
||||
*/
|
||||
Expr basicNullGuard(Expr e, boolean branch, boolean isnull) {
|
||||
exists(AnyEqualityTest eqtest, boolean polarity |
|
||||
exists(EqualityTest eqtest, boolean polarity |
|
||||
eqtest = result and
|
||||
eqtest.hasOperands(e, any(NullLiteral n)) and
|
||||
polarity = eqtest.polarity() and
|
||||
@@ -193,7 +193,7 @@ Expr basicNullGuard(Expr e, boolean branch, boolean isnull) {
|
||||
nullCheckMethod(call.getMethod(), branch, isnull)
|
||||
)
|
||||
or
|
||||
exists(AnyEqualityTest eqtest |
|
||||
exists(EqualityTest eqtest |
|
||||
eqtest = result and
|
||||
eqtest.hasOperands(e, clearlyNotNullExpr()) and
|
||||
isnull = false and
|
||||
|
||||
@@ -70,13 +70,13 @@ private predicate unboxed(Expr e) {
|
||||
or
|
||||
exists(AssignOp assign | assign.getSource() = e and assign.getType() instanceof PrimitiveType)
|
||||
or
|
||||
exists(AnyEqualityTest eq |
|
||||
exists(EqualityTest eq |
|
||||
eq.getAnOperand() = e and eq.getAnOperand().getType() instanceof PrimitiveType
|
||||
)
|
||||
or
|
||||
exists(BinaryExpr bin |
|
||||
bin.getAnOperand() = e and
|
||||
not bin instanceof AnyEqualityTest and
|
||||
not bin instanceof EqualityTest and
|
||||
bin.getType() instanceof PrimitiveType
|
||||
)
|
||||
or
|
||||
@@ -653,7 +653,7 @@ private Expr trackingVarGuard(
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(AnyEqualityTest eqtest, boolean branch0, boolean polarity, BooleanLiteral boollit |
|
||||
exists(EqualityTest eqtest, boolean branch0, boolean polarity, BooleanLiteral boollit |
|
||||
eqtest = result and
|
||||
eqtest.hasOperands(trackingVarGuard(trackssa, trackvar, kind, branch0, isA), boollit) and
|
||||
eqtest.polarity() = polarity and
|
||||
|
||||
@@ -387,7 +387,7 @@ private predicate taintPreservingArgumentToQualifier(Method method, int arg) {
|
||||
/** A comparison or equality test with a constant. */
|
||||
private predicate comparisonStep(Expr tracked, Expr sink) {
|
||||
exists(Expr other |
|
||||
exists(BinaryExpr e | e instanceof ComparisonExpr or e instanceof AnyEqualityTest |
|
||||
exists(BinaryExpr e | e instanceof ComparisonExpr or e instanceof EqualityTest |
|
||||
e = sink and
|
||||
e.hasOperands(tracked, other)
|
||||
)
|
||||
|
||||
@@ -116,7 +116,7 @@ private predicate intentFlagsOrDataChecked(Guard g, Expr intent, boolean branch)
|
||||
bitwiseLocalTaintStep*(DataFlow::exprNode(ma), DataFlow::exprNode(checkedValue))
|
||||
|
|
||||
bitwiseCheck(g, branch) and
|
||||
checkedValue = g.(AnyEqualityTest).getAnOperand().(AndBitwiseExpr)
|
||||
checkedValue = g.(EqualityTest).getAnOperand().(AndBitwiseExpr)
|
||||
or
|
||||
g.(MethodAccess).getMethod() instanceof EqualsMethod and
|
||||
branch = true and
|
||||
@@ -129,10 +129,10 @@ private predicate intentFlagsOrDataChecked(Guard g, Expr intent, boolean branch)
|
||||
* and `false` otherwise.
|
||||
*/
|
||||
private predicate bitwiseCheck(Guard g, boolean branch) {
|
||||
exists(CompileTimeConstantExpr operand | operand = g.(AnyEqualityTest).getAnOperand() |
|
||||
exists(CompileTimeConstantExpr operand | operand = g.(EqualityTest).getAnOperand() |
|
||||
if operand.getIntValue() = 0
|
||||
then g.(AnyEqualityTest).polarity() = branch
|
||||
else g.(AnyEqualityTest).polarity().booleanNot() = branch
|
||||
then g.(EqualityTest).polarity() = branch
|
||||
else g.(EqualityTest).polarity().booleanNot() = branch
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ class ShiftExpr extends BinaryExpr {
|
||||
*/
|
||||
class RelationExpr extends BinaryExpr {
|
||||
RelationExpr() {
|
||||
this instanceof AnyEqualityTest or
|
||||
this instanceof EqualityTest or
|
||||
this instanceof ComparisonExpr
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,7 @@ class AssocNestedExpr extends BinaryExpr {
|
||||
parent.getKind() = this.getKind()
|
||||
or
|
||||
// Equality tests are associate over each other.
|
||||
this instanceof AnyEqualityTest and parent instanceof AnyEqualityTest
|
||||
this instanceof EqualityTest and parent instanceof EqualityTest
|
||||
or
|
||||
// (x*y)/z = x*(y/z)
|
||||
this instanceof MulExpr and parent instanceof DivExpr and idx = 0
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
import java
|
||||
|
||||
predicate comparison(BinaryExpr binop, Expr left, Expr right) {
|
||||
(binop instanceof ComparisonExpr or binop instanceof AnyEqualityTest) and
|
||||
(binop instanceof ComparisonExpr or binop instanceof EqualityTest) and
|
||||
binop.getLeftOperand() = left and
|
||||
binop.getRightOperand() = right
|
||||
}
|
||||
@@ -64,7 +64,7 @@ predicate equal(Expr left, Expr right) {
|
||||
)
|
||||
}
|
||||
|
||||
predicate specialCase(AnyEqualityTest comparison, string msg) {
|
||||
predicate specialCase(EqualityTest comparison, string msg) {
|
||||
exists(FloatingPointType fptp, string neg, string boxedName |
|
||||
fptp = comparison.getAnOperand().getType() and
|
||||
// Name of boxed type corresponding to `fptp`.
|
||||
|
||||
@@ -25,7 +25,7 @@ class BooleanExpr extends Expr {
|
||||
private predicate assignAndCheck(AssignExpr e) {
|
||||
exists(BinaryExpr c | e = c.getAChildExpr() |
|
||||
c instanceof ComparisonExpr or
|
||||
c instanceof AnyEqualityTest
|
||||
c instanceof EqualityTest
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ predicate comparisonMethod(Method m) { m.getName() = "compareTo" }
|
||||
|
||||
// Check for equalities of the form `a.x == b.x` or `a.x == x`, where `x` is assigned to `a.x`,
|
||||
// which are less interesting but occur often.
|
||||
predicate similarVarComparison(AnyEqualityTest e) {
|
||||
predicate similarVarComparison(EqualityTest e) {
|
||||
exists(Field f |
|
||||
e.getLeftOperand() = f.getAnAccess() and
|
||||
e.getRightOperand() = f.getAnAccess()
|
||||
@@ -59,7 +59,7 @@ predicate similarVarComparison(AnyEqualityTest e) {
|
||||
)
|
||||
}
|
||||
|
||||
from AnyEqualityTest ee
|
||||
from EqualityTest ee
|
||||
where
|
||||
ee.getAnOperand().getType() instanceof Floating and
|
||||
not ee.getAnOperand() instanceof NullLiteral and
|
||||
|
||||
@@ -19,7 +19,7 @@ class FinalFieldAccess extends VarAccess {
|
||||
FinalFieldAccess() { this.getVariable().(Field).isFinal() }
|
||||
}
|
||||
|
||||
class ReferenceEqualityTestOnObject extends EqualityTest {
|
||||
class ReferenceEqualityTestOnObject extends ReferenceEqualityTest {
|
||||
ReferenceEqualityTestOnObject() {
|
||||
this.getLeftOperand().getType() instanceof TypeObject and
|
||||
this.getRightOperand().getType() instanceof TypeObject and
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
import java
|
||||
|
||||
from EqualityTest c
|
||||
from ReferenceEqualityTest c
|
||||
where
|
||||
c.getLeftOperand().getType() instanceof BoxedType and
|
||||
c.getRightOperand().getType() instanceof BoxedType and
|
||||
|
||||
@@ -57,7 +57,7 @@ predicate variableValuesInterned(Variable v) {
|
||||
forall(StringValue sv | sv = v.getAnAssignedValue() | sv.isInterned())
|
||||
}
|
||||
|
||||
from EqualityTest e, StringValue lhs, StringValue rhs
|
||||
from ReferenceEqualityTest e, StringValue lhs, StringValue rhs
|
||||
where
|
||||
e.getLeftOperand() = lhs and
|
||||
e.getRightOperand() = rhs and
|
||||
|
||||
@@ -44,7 +44,7 @@ predicate constCond(BinaryExpr cond, boolean isTrue, Reason reason) {
|
||||
isTrue = false and not comp.isStrict() and d1 > d2
|
||||
)
|
||||
or
|
||||
exists(AnyEqualityTest eq, Expr lhs, Expr rhs |
|
||||
exists(EqualityTest eq, Expr lhs, Expr rhs |
|
||||
eq = cond and
|
||||
lhs = eq.getLeftOperand() and
|
||||
rhs = eq.getRightOperand()
|
||||
@@ -192,7 +192,7 @@ predicate concurrentModificationTest(BinaryExpr test) {
|
||||
* Holds if `test` and `guard` are equality tests of the same integral variable v with constants `c1` and `c2`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate guardedTest(AnyEqualityTest test, Guard guard, boolean isEq, int i1, int i2) {
|
||||
predicate guardedTest(EqualityTest test, Guard guard, boolean isEq, int i1, int i2) {
|
||||
exists(SsaVariable v, CompileTimeConstantExpr c1, CompileTimeConstantExpr c2 |
|
||||
guard.isEquality(v.getAUse(), c1, isEq) and
|
||||
test.hasOperands(v.getAUse(), c2) and
|
||||
@@ -205,7 +205,7 @@ predicate guardedTest(AnyEqualityTest test, Guard guard, boolean isEq, int i1, i
|
||||
/**
|
||||
* Holds if `guard` implies that `test` always has the value `testIsTrue`.
|
||||
*/
|
||||
predicate uselessEqTest(AnyEqualityTest test, boolean testIsTrue, Guard guard) {
|
||||
predicate uselessEqTest(EqualityTest test, boolean testIsTrue, Guard guard) {
|
||||
exists(boolean guardIsTrue, boolean guardpolarity, int i |
|
||||
guardedTest(test, guard, guardpolarity, i, i) and
|
||||
guard.controls(test.getBasicBlock(), guardIsTrue) and
|
||||
@@ -218,7 +218,7 @@ where
|
||||
(
|
||||
if uselessEqTest(test, _, _)
|
||||
then
|
||||
exists(AnyEqualityTest r |
|
||||
exists(EqualityTest r |
|
||||
uselessEqTest(test, testIsTrue, r) and reason = ", because of $@" and reasonElem = r
|
||||
)
|
||||
else
|
||||
|
||||
@@ -42,7 +42,7 @@ predicate uselessTest(ConditionNode s1, BinaryExpr test, boolean testIsTrue) {
|
||||
exists(BoundKind boundKind, int bound |
|
||||
// Simple range analysis. We infer a bound based on `cond` being
|
||||
// either true (`condIsTrue = true`) or false (`condIsTrue = false`).
|
||||
exists(AnyEqualityTest condeq | cond = condeq and bound = k1 |
|
||||
exists(EqualityTest condeq | cond = condeq and bound = k1 |
|
||||
condIsTrue = condeq.polarity() and boundKind.isEqual()
|
||||
or
|
||||
condIsTrue = condeq.polarity().booleanNot() and boundKind.isNotEqual()
|
||||
@@ -74,7 +74,7 @@ predicate uselessTest(ConditionNode s1, BinaryExpr test, boolean testIsTrue) {
|
||||
|
|
||||
// Given the bound we check if the `test` is either
|
||||
// always true (`testIsTrue = true`) or always false (`testIsTrue = false`).
|
||||
exists(AnyEqualityTest testeq, boolean pol | testeq = test and pol = testeq.polarity() |
|
||||
exists(EqualityTest testeq, boolean pol | testeq = test and pol = testeq.polarity() |
|
||||
(
|
||||
boundKind.providesLowerBound() and k2 < bound
|
||||
or
|
||||
|
||||
@@ -16,7 +16,7 @@ predicate nanField(Field f) {
|
||||
f.hasName("NaN")
|
||||
}
|
||||
|
||||
from AnyEqualityTest eq, Field f, string classname
|
||||
from EqualityTest eq, Field f, string classname
|
||||
where
|
||||
eq.getAnOperand() = f.getAnAccess() and nanField(f) and f.getDeclaringType().hasName(classname)
|
||||
select eq,
|
||||
|
||||
@@ -21,7 +21,7 @@ private Expr getAFieldRead(Field f) {
|
||||
* `f` or indirectly through a local variable `(x = f) == null`.
|
||||
*/
|
||||
private Expr getANullCheck(Field f) {
|
||||
exists(AnyEqualityTest eq | eq.polarity() = true |
|
||||
exists(EqualityTest eq | eq.polarity() = true |
|
||||
eq.hasOperands(any(NullLiteral nl), getAFieldRead(f)) and
|
||||
result = eq
|
||||
)
|
||||
|
||||
@@ -17,7 +17,7 @@ import java
|
||||
class ComparisonOrEqTestExpr extends Expr {
|
||||
ComparisonOrEqTestExpr() {
|
||||
this instanceof ComparisonExpr or
|
||||
this instanceof EqualityTest
|
||||
this instanceof ReferenceEqualityTest
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ private predicate inWeakCheck(Expr e) {
|
||||
)
|
||||
or
|
||||
// Checking against `null` has no bearing on path traversal.
|
||||
exists(AnyEqualityTest b | b.getAnOperand() = e | b.getAnOperand() instanceof NullLiteral)
|
||||
exists(EqualityTest b | b.getAnOperand() = e | b.getAnOperand() instanceof NullLiteral)
|
||||
}
|
||||
|
||||
// Ignore cases where the variable has been checked somehow,
|
||||
|
||||
@@ -46,7 +46,7 @@ predicate boundedRead(RValue read) {
|
||||
}
|
||||
|
||||
predicate castCheck(RValue read) {
|
||||
exists(AnyEqualityTest eq, CastExpr cast |
|
||||
exists(EqualityTest eq, CastExpr cast |
|
||||
cast.getExpr() = read and
|
||||
eq.hasOperands(cast, read.getVariable().getAnAccess())
|
||||
)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
import java
|
||||
|
||||
class BoolCompare extends AnyEqualityTest {
|
||||
class BoolCompare extends EqualityTest {
|
||||
BoolCompare() { this.getAnOperand() instanceof BooleanLiteral }
|
||||
|
||||
predicate simplify(string pattern, string rewrite) {
|
||||
@@ -61,7 +61,7 @@ predicate conditionalWithBool(ConditionalExpr c, string pattern, string rewrite)
|
||||
}
|
||||
|
||||
class ComparisonOrEquality extends BinaryExpr {
|
||||
ComparisonOrEquality() { this instanceof ComparisonExpr or this instanceof AnyEqualityTest }
|
||||
ComparisonOrEquality() { this instanceof ComparisonExpr or this instanceof EqualityTest }
|
||||
|
||||
predicate negate(string pattern, string rewrite) {
|
||||
this instanceof EQExpr and pattern = "!(A == B)" and rewrite = "A != B"
|
||||
|
||||
@@ -36,7 +36,7 @@ Variable flowTarget(Expr arg) {
|
||||
*/
|
||||
predicate unboxed(BoxedExpr e) {
|
||||
exists(BinaryExpr bin | e = bin.getAnOperand() |
|
||||
if bin instanceof AnyEqualityTest or bin instanceof ComparisonExpr
|
||||
if bin instanceof EqualityTest or bin instanceof ComparisonExpr
|
||||
then bin.getAnOperand() instanceof PrimitiveExpr
|
||||
else bin instanceof PrimitiveExpr
|
||||
)
|
||||
|
||||
@@ -266,7 +266,7 @@ private predicate isNonConstantTimeComparisonCall(Expr firstInput, Expr secondIn
|
||||
*/
|
||||
private predicate existsFailFastCheck(Expr firstArray, Expr secondArray) {
|
||||
exists(
|
||||
Guard guard, AnyEqualityTest eqTest, boolean branch, Stmt fastFailingStmt,
|
||||
Guard guard, EqualityTest eqTest, boolean branch, Stmt fastFailingStmt,
|
||||
ArrayAccess firstArrayAccess, ArrayAccess secondArrayAccess
|
||||
|
|
||||
guard = eqTest and
|
||||
|
||||
Reference in New Issue
Block a user