Java: Add InstanceOfExpr.getCheckedType()

Additionally change `EqualsUsesInstanceOf.ql` to check for all RefTypes
instead of only Class.
This commit is contained in:
Marcono1234
2021-07-10 20:00:21 +02:00
parent 0e9d36b922
commit 606173012a
12 changed files with 18 additions and 15 deletions

View File

@@ -17,7 +17,7 @@ from InstanceOfExpr ioe, RefType t, RefType ct
where where
ioe.getExpr() instanceof ThisAccess and ioe.getExpr() instanceof ThisAccess and
t = ioe.getExpr().getType() and t = ioe.getExpr().getType() and
ct = ioe.getTypeName().getType() and ct = ioe.getCheckedType() and
ct.getASupertype*() = t ct.getASupertype*() = t
select ioe, select ioe,
"Testing whether 'this' is an instance of $@ in $@ introduces a dependency cycle between the two types.", "Testing whether 'this' is an instance of $@ in $@ introduces a dependency cycle between the two types.",

View File

@@ -15,7 +15,7 @@ import java
from InstanceOfExpr ioe, RefType t, RefType ct from InstanceOfExpr ioe, RefType t, RefType ct
where where
t = ioe.getExpr().getType() and t = ioe.getExpr().getType() and
ct = ioe.getTypeName().getType() and ct = ioe.getCheckedType() and
ct = t.getASupertype+() ct = t.getASupertype+()
select ioe, select ioe,
"There is no need to test whether an instance of $@ is also an instance of $@ - it always is.", t, "There is no need to test whether an instance of $@ is also an instance of $@ - it always is.", t,

View File

@@ -17,8 +17,8 @@ predicate instanceofInEquals(EqualsMethod m, InstanceOfExpr e) {
m.fromSource() and m.fromSource() and
e.getEnclosingCallable() = m and e.getEnclosingCallable() = m and
e.getExpr().(VarAccess).getVariable() = m.getParameter() and e.getExpr().(VarAccess).getVariable() = m.getParameter() and
exists(Class instanceofType | exists(RefType instanceofType |
instanceofType = e.getTypeName().getType() and instanceofType = e.getCheckedType() and
not instanceofType.isFinal() not instanceofType.isFinal()
) )
} }

View File

@@ -18,7 +18,7 @@ import semmle.code.java.dataflow.SSA
/** `ioe` is of the form `va instanceof t`. */ /** `ioe` is of the form `va instanceof t`. */
predicate instanceOfCheck(InstanceOfExpr ioe, VarAccess va, RefType t) { predicate instanceOfCheck(InstanceOfExpr ioe, VarAccess va, RefType t) {
ioe.getExpr() = va and ioe.getExpr() = va and
ioe.getTypeName().getType().(RefType).getSourceDeclaration() = t ioe.getCheckedType().getSourceDeclaration() = t
} }
/** Expression `e` assumes that `va` could be of type `t`. */ /** Expression `e` assumes that `va` could be of type `t`. */

View File

@@ -16,9 +16,9 @@ import java
import semmle.code.java.Collections import semmle.code.java.Collections
predicate guardedByInstanceOf(VarAccess e, RefType t) { predicate guardedByInstanceOf(VarAccess e, RefType t) {
exists(IfStmt s, InstanceOfExpr instanceCheck, Type checkType | exists(IfStmt s, InstanceOfExpr instanceCheck, RefType checkType |
s.getCondition() = instanceCheck and s.getCondition() = instanceCheck and
instanceCheck.getTypeName().getType() = checkType and instanceCheck.getCheckedType() = checkType and
// The same variable appears as the subject of the `instanceof`. // The same variable appears as the subject of the `instanceof`.
instanceCheck.getExpr() = e.getVariable().getAnAccess() and instanceCheck.getExpr() = e.getVariable().getAnAccess() and
// The checked type is either the type itself, or a raw version. For example, it is usually // The checked type is either the type itself, or a raw version. For example, it is usually

View File

@@ -76,7 +76,7 @@ predicate depends(RefType t, RefType dep) {
or or
// the type accessed in an `instanceof` expression in `t`. // the type accessed in an `instanceof` expression in `t`.
exists(InstanceOfExpr ioe | t = ioe.getEnclosingCallable().getDeclaringType() | exists(InstanceOfExpr ioe | t = ioe.getEnclosingCallable().getDeclaringType() |
usesType(ioe.getTypeName().getType(), dep) usesType(ioe.getCheckedType(), dep)
) )
) )
} }

View File

@@ -100,7 +100,7 @@ predicate numDepends(RefType t, RefType dep, int value) {
elem = ioe and elem = ioe and
t = ioe.getEnclosingCallable().getDeclaringType() t = ioe.getEnclosingCallable().getDeclaringType()
| |
usesType(ioe.getTypeName().getType(), dep) usesType(ioe.getCheckedType(), dep)
) )
) )
} }

View File

@@ -1333,6 +1333,9 @@ class InstanceOfExpr extends Expr, @instanceofexpr {
/** Gets the access to the type on the right-hand side of the `instanceof` operator. */ /** Gets the access to the type on the right-hand side of the `instanceof` operator. */
Expr getTypeName() { result.isNthChildOf(this, 1) } Expr getTypeName() { result.isNthChildOf(this, 1) }
/** Gets the type this `instanceof` expression checks for. */
RefType getCheckedType() { result = getTypeName().getType() }
/** Gets a printable representation of this expression. */ /** Gets a printable representation of this expression. */
override string toString() { result = "...instanceof..." } override string toString() { result = "...instanceof..." }

View File

@@ -25,8 +25,8 @@ Expr enumConstEquality(Expr e, boolean polarity, EnumConstant c) {
} }
/** Gets an instanceof expression of `v` with type `type` */ /** Gets an instanceof expression of `v` with type `type` */
InstanceOfExpr instanceofExpr(SsaVariable v, Type type) { InstanceOfExpr instanceofExpr(SsaVariable v, RefType type) {
result.getTypeName().getType() = type and result.getCheckedType() = type and
result.getExpr() = v.getAUse() result.getExpr() = v.getAUse()
} }

View File

@@ -504,7 +504,7 @@ private predicate correlatedConditions(
inverted = pol1.booleanXor(pol2) inverted = pol1.booleanXor(pol2)
) )
or or
exists(SsaVariable v, Type type | exists(SsaVariable v, RefType type |
cond1.getCondition() = instanceofExpr(v, type) and cond1.getCondition() = instanceofExpr(v, type) and
cond2.getCondition() = instanceofExpr(v, type) and cond2.getCondition() = instanceofExpr(v, type) and
inverted = false inverted = false

View File

@@ -299,7 +299,7 @@ private predicate downcastSuccessor(VarAccess va, RefType t) {
private predicate instanceOfGuarded(VarAccess va, RefType t) { private predicate instanceOfGuarded(VarAccess va, RefType t) {
exists(InstanceOfExpr ioe, BaseSsaVariable v | exists(InstanceOfExpr ioe, BaseSsaVariable v |
ioe.getExpr() = v.getAUse() and ioe.getExpr() = v.getAUse() and
t = ioe.getTypeName().getType() and t = ioe.getCheckedType() and
va = v.getAUse() and va = v.getAUse() and
guardControls_v1(ioe, va.getBasicBlock(), true) guardControls_v1(ioe, va.getBasicBlock(), true)
) )
@@ -311,7 +311,7 @@ private predicate instanceOfGuarded(VarAccess va, RefType t) {
predicate arrayInstanceOfGuarded(ArrayAccess aa, RefType t) { predicate arrayInstanceOfGuarded(ArrayAccess aa, RefType t) {
exists(InstanceOfExpr ioe, BaseSsaVariable v1, BaseSsaVariable v2, ArrayAccess aa1 | exists(InstanceOfExpr ioe, BaseSsaVariable v1, BaseSsaVariable v2, ArrayAccess aa1 |
ioe.getExpr() = aa1 and ioe.getExpr() = aa1 and
t = ioe.getTypeName().getType() and t = ioe.getCheckedType() and
aa1.getArray() = v1.getAUse() and aa1.getArray() = v1.getAUse() and
aa1.getIndexExpr() = v2.getAUse() and aa1.getIndexExpr() = v2.getAUse() and
aa.getArray() = v1.getAUse() and aa.getArray() = v1.getAUse() and

View File

@@ -176,7 +176,7 @@ private module Dispatch {
v.getAUse() = q and v.getAUse() = q and
guardControls_v1(ioe, q.getBasicBlock(), false) and guardControls_v1(ioe, q.getBasicBlock(), false) and
ioe.getExpr() = v.getAUse() and ioe.getExpr() = v.getAUse() and
ioe.getTypeName().getType().getErasure() = t and ioe.getCheckedType().getErasure() = t and
tgt.getDeclaringType().getSourceDeclaration().getASourceSupertype*() = t tgt.getDeclaringType().getSourceDeclaration().getASourceSupertype*() = t
) )
} }