mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Java: Replace BaseSSA class wrappers with shared code.
This commit is contained in:
@@ -141,7 +141,7 @@ private predicate isNonFallThroughPredecessor(SwitchCase sc, ControlFlowNode pre
|
||||
|
||||
private module GuardsInput implements SharedGuards::InputSig<Location, ControlFlowNode, BasicBlock> {
|
||||
private import java as J
|
||||
private import semmle.code.java.dataflow.internal.BaseSSA
|
||||
private import semmle.code.java.dataflow.internal.BaseSSA as Base
|
||||
private import semmle.code.java.dataflow.NullGuards as NullGuards
|
||||
|
||||
class NormalExitNode = ControlFlow::NormalExitNode;
|
||||
@@ -211,10 +211,10 @@ private module GuardsInput implements SharedGuards::InputSig<Location, ControlFl
|
||||
f.getInitializer() = NullGuards::baseNotNullExpr()
|
||||
)
|
||||
or
|
||||
exists(CatchClause cc, LocalVariableDeclExpr decl, BaseSsaUpdate v |
|
||||
exists(CatchClause cc, LocalVariableDeclExpr decl, Base::SsaExplicitWrite v |
|
||||
decl = cc.getVariable() and
|
||||
decl = v.getDefiningExpr() and
|
||||
this = v.getAUse()
|
||||
this = v.getARead()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -407,30 +407,8 @@ private module LogicInputCommon {
|
||||
}
|
||||
|
||||
private module LogicInput_v1 implements GuardsImpl::LogicInputSig {
|
||||
private import semmle.code.java.dataflow.internal.BaseSSA
|
||||
|
||||
final private class FinalBaseSsaVariable = BaseSsaVariable;
|
||||
|
||||
class SsaDefinition extends FinalBaseSsaVariable {
|
||||
GuardsInput::Expr getARead() { result = this.getAUse() }
|
||||
}
|
||||
|
||||
class SsaExplicitWrite extends SsaDefinition instanceof BaseSsaUpdate {
|
||||
GuardsInput::Expr getValue() {
|
||||
super.getDefiningExpr().(VariableAssign).getSource() = result or
|
||||
super.getDefiningExpr().(AssignOp) = result
|
||||
}
|
||||
}
|
||||
|
||||
class SsaPhiDefinition extends SsaDefinition instanceof BaseSsaPhiNode {
|
||||
predicate hasInputFromBlock(SsaDefinition inp, BasicBlock bb) {
|
||||
super.hasInputFromBlock(inp, bb)
|
||||
}
|
||||
}
|
||||
|
||||
class SsaParameterInit extends SsaDefinition instanceof BaseSsaImplicitInit {
|
||||
Parameter getParameter() { super.isParameterDefinition(result) }
|
||||
}
|
||||
private import semmle.code.java.dataflow.internal.BaseSSA as Base
|
||||
import Base::Ssa
|
||||
|
||||
predicate additionalNullCheck = LogicInputCommon::additionalNullCheck/4;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ module;
|
||||
|
||||
import java as J
|
||||
private import semmle.code.java.dispatch.VirtualDispatch
|
||||
private import semmle.code.java.dataflow.internal.BaseSSA
|
||||
private import semmle.code.java.dataflow.internal.BaseSSA as Base
|
||||
private import semmle.code.java.controlflow.Guards
|
||||
private import codeql.typeflow.TypeFlow
|
||||
private import codeql.typeflow.UniversalFlow as UniversalFlow
|
||||
@@ -27,7 +27,7 @@ private RefType boxIfNeeded(J::Type t) {
|
||||
module FlowStepsInput implements UniversalFlow::UniversalFlowInput<Location> {
|
||||
private newtype TFlowNode =
|
||||
TField(Field f) { not f.getType() instanceof PrimitiveType } or
|
||||
TSsa(BaseSsaVariable ssa) { not ssa.getSourceVariable().getType() instanceof PrimitiveType } or
|
||||
TSsa(Base::SsaDefinition ssa) { not ssa.getSourceVariable().getType() instanceof PrimitiveType } or
|
||||
TExpr(Expr e) or
|
||||
TMethod(Method m) { not m.getReturnType() instanceof PrimitiveType }
|
||||
|
||||
@@ -55,7 +55,7 @@ module FlowStepsInput implements UniversalFlow::UniversalFlowInput<Location> {
|
||||
Field asField() { this = TField(result) }
|
||||
|
||||
/** Gets the SSA variable corresponding to this node, if any. */
|
||||
BaseSsaVariable asSsa() { this = TSsa(result) }
|
||||
Base::SsaDefinition asSsa() { this = TSsa(result) }
|
||||
|
||||
/** Gets the expression corresponding to this node, if any. */
|
||||
Expr asExpr() { this = TExpr(result) }
|
||||
@@ -107,7 +107,7 @@ module FlowStepsInput implements UniversalFlow::UniversalFlowInput<Location> {
|
||||
not e.(FieldAccess).getField() = f
|
||||
)
|
||||
or
|
||||
n2.asSsa().(BaseSsaPhiNode).getAnUltimateLocalDefinition() = n1.asSsa()
|
||||
n2.asSsa().(Base::SsaPhiDefinition).getAnUltimateDefinition() = n1.asSsa()
|
||||
or
|
||||
exists(ReturnStmt ret |
|
||||
n2.asMethod() = ret.getEnclosingCallable() and ret.getResult() = n1.asExpr()
|
||||
@@ -118,14 +118,14 @@ module FlowStepsInput implements UniversalFlow::UniversalFlowInput<Location> {
|
||||
exists(Argument arg, Parameter p |
|
||||
privateParamArg(p, arg) and
|
||||
n1.asExpr() = arg and
|
||||
n2.asSsa().(BaseSsaImplicitInit).isParameterDefinition(p) and
|
||||
n2.asSsa().(Base::SsaParameterInit).getParameter() = p and
|
||||
// skip trivial recursion
|
||||
not arg = n2.asSsa().getAUse()
|
||||
not arg = n2.asSsa().getARead()
|
||||
)
|
||||
or
|
||||
n2.asExpr() = n1.asField().getAnAccess()
|
||||
or
|
||||
n2.asExpr() = n1.asSsa().getAUse()
|
||||
n2.asExpr() = n1.asSsa().getARead()
|
||||
or
|
||||
n2.asExpr().(CastingExpr).getExpr() = n1.asExpr() and
|
||||
not n2.asExpr().getType() instanceof PrimitiveType
|
||||
@@ -133,9 +133,9 @@ module FlowStepsInput implements UniversalFlow::UniversalFlowInput<Location> {
|
||||
n2.asExpr().(AssignExpr).getSource() = n1.asExpr() and
|
||||
not n2.asExpr().getType() instanceof PrimitiveType
|
||||
or
|
||||
n2.asSsa().(BaseSsaUpdate).getDefiningExpr().(VariableAssign).getSource() = n1.asExpr()
|
||||
n2.asSsa().(Base::SsaExplicitWrite).getDefiningExpr().(VariableAssign).getSource() = n1.asExpr()
|
||||
or
|
||||
n2.asSsa().(BaseSsaImplicitInit).captures(n1.asSsa())
|
||||
n2.asSsa().(Base::SsaCapturedDefinition).captures(n1.asSsa())
|
||||
or
|
||||
n2.asExpr().(NotNullExpr).getExpr() = n1.asExpr()
|
||||
}
|
||||
@@ -147,7 +147,7 @@ module FlowStepsInput implements UniversalFlow::UniversalFlowInput<Location> {
|
||||
n.asExpr() instanceof NullLiteral
|
||||
or
|
||||
exists(LocalVariableDeclExpr decl |
|
||||
n.asSsa().(BaseSsaUpdate).getDefiningExpr() = decl and
|
||||
n.asSsa().(Base::SsaExplicitWrite).getDefiningExpr() = decl and
|
||||
not decl.hasImplicitInit() and
|
||||
not exists(decl.getInitOrPatternSource())
|
||||
)
|
||||
@@ -216,7 +216,9 @@ private module Input implements TypeFlowInput<Location> {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate upcastEnhancedForStmtAux(BaseSsaUpdate v, RefType t, RefType t1, RefType t2) {
|
||||
private predicate upcastEnhancedForStmtAux(
|
||||
Base::SsaExplicitWrite v, RefType t, RefType t1, RefType t2
|
||||
) {
|
||||
exists(EnhancedForStmt for |
|
||||
for.getVariable() = v.getDefiningExpr() and
|
||||
v.getSourceVariable().getType().getErasure() = t2 and
|
||||
@@ -230,7 +232,7 @@ private module Input implements TypeFlowInput<Location> {
|
||||
* the type of the elements being iterated over, and this type is more precise
|
||||
* than the type of `v`.
|
||||
*/
|
||||
private predicate upcastEnhancedForStmt(BaseSsaUpdate v, RefType t) {
|
||||
private predicate upcastEnhancedForStmt(Base::SsaExplicitWrite v, RefType t) {
|
||||
exists(RefType t1, RefType t2 |
|
||||
upcastEnhancedForStmtAux(v, t, t1, t2) and
|
||||
t1.getASourceSupertype+() = t2
|
||||
@@ -238,9 +240,9 @@ private module Input implements TypeFlowInput<Location> {
|
||||
}
|
||||
|
||||
private predicate downcastSuccessorAux(
|
||||
CastingExpr cast, BaseSsaVariable v, RefType t, RefType t1, RefType t2
|
||||
CastingExpr cast, Base::SsaDefinition v, RefType t, RefType t1, RefType t2
|
||||
) {
|
||||
cast.getExpr() = v.getAUse() and
|
||||
cast.getExpr() = v.getARead() and
|
||||
t = cast.getType() and
|
||||
t1 = t.getErasure() and
|
||||
t2 = v.getSourceVariable().getType().getErasure()
|
||||
@@ -250,10 +252,10 @@ private module Input implements TypeFlowInput<Location> {
|
||||
* Holds if `va` is an access to a value that has previously been downcast to `t`.
|
||||
*/
|
||||
private predicate downcastSuccessor(VarAccess va, RefType t) {
|
||||
exists(CastingExpr cast, BaseSsaVariable v, RefType t1, RefType t2 |
|
||||
exists(CastingExpr cast, Base::SsaDefinition v, RefType t1, RefType t2 |
|
||||
downcastSuccessorAux(pragma[only_bind_into](cast), v, t, t1, t2) and
|
||||
t1.getASourceSupertype+() = t2 and
|
||||
va = v.getAUse() and
|
||||
va = v.getARead() and
|
||||
dominates(cast.getControlFlowNode(), va.getControlFlowNode()) and
|
||||
dominates(cast.getControlFlowNode().getANormalSuccessor(), va.getControlFlowNode())
|
||||
)
|
||||
@@ -263,9 +265,9 @@ private module Input implements TypeFlowInput<Location> {
|
||||
* Holds if `va` is an access to a value that is guarded by `instanceof t` or `case e t`.
|
||||
*/
|
||||
private predicate typeTestGuarded(VarAccess va, RefType t) {
|
||||
exists(Guard typeTest, BaseSsaVariable v |
|
||||
typeTest.appliesTypeTest(v.getAUse(), t, _) and
|
||||
va = v.getAUse() and
|
||||
exists(Guard typeTest, Base::SsaDefinition v |
|
||||
typeTest.appliesTypeTest(v.getARead(), t, _) and
|
||||
va = v.getARead() and
|
||||
guardControls_v1(typeTest, va.getBasicBlock(), true)
|
||||
)
|
||||
}
|
||||
@@ -274,12 +276,12 @@ private module Input implements TypeFlowInput<Location> {
|
||||
* Holds if `aa` is an access to a value that is guarded by `instanceof t` or `case e t`.
|
||||
*/
|
||||
private predicate arrayTypeTestGuarded(ArrayAccess aa, RefType t) {
|
||||
exists(Guard typeTest, BaseSsaVariable v1, BaseSsaVariable v2, ArrayAccess aa1 |
|
||||
exists(Guard typeTest, Base::SsaDefinition v1, Base::SsaDefinition v2, ArrayAccess aa1 |
|
||||
typeTest.appliesTypeTest(aa1, t, _) and
|
||||
aa1.getArray() = v1.getAUse() and
|
||||
aa1.getIndexExpr() = v2.getAUse() and
|
||||
aa.getArray() = v1.getAUse() and
|
||||
aa.getIndexExpr() = v2.getAUse() and
|
||||
aa1.getArray() = v1.getARead() and
|
||||
aa1.getIndexExpr() = v2.getARead() and
|
||||
aa.getArray() = v1.getARead() and
|
||||
aa.getIndexExpr() = v2.getARead() and
|
||||
guardControls_v1(typeTest, aa.getBasicBlock(), true)
|
||||
)
|
||||
}
|
||||
@@ -321,14 +323,14 @@ private module Input implements TypeFlowInput<Location> {
|
||||
* Holds if `ioe` checks `v`, its true-successor is `bb`, and `bb` has multiple
|
||||
* predecessors.
|
||||
*/
|
||||
private predicate instanceofDisjunct(InstanceOfExpr ioe, BasicBlock bb, BaseSsaVariable v) {
|
||||
ioe.getExpr() = v.getAUse() and
|
||||
private predicate instanceofDisjunct(InstanceOfExpr ioe, BasicBlock bb, Base::SsaDefinition v) {
|
||||
ioe.getExpr() = v.getARead() and
|
||||
strictcount(bb.getAPredecessor()) > 1 and
|
||||
exists(ConditionBlock cb | cb.getCondition() = ioe and cb.getTestSuccessor(true) = bb)
|
||||
}
|
||||
|
||||
/** Holds if `bb` is disjunctively guarded by multiple `instanceof` tests on `v`. */
|
||||
private predicate instanceofDisjunction(BasicBlock bb, BaseSsaVariable v) {
|
||||
private predicate instanceofDisjunction(BasicBlock bb, Base::SsaDefinition v) {
|
||||
strictcount(InstanceOfExpr ioe | instanceofDisjunct(ioe, bb, v)) =
|
||||
strictcount(bb.getAPredecessor())
|
||||
}
|
||||
@@ -338,10 +340,10 @@ private module Input implements TypeFlowInput<Location> {
|
||||
* `instanceof t_i` where `t` is one of those `t_i`.
|
||||
*/
|
||||
predicate instanceofDisjunctionGuarded(TypeFlowNode n, RefType t) {
|
||||
exists(BasicBlock bb, InstanceOfExpr ioe, BaseSsaVariable v, VarAccess va |
|
||||
exists(BasicBlock bb, InstanceOfExpr ioe, Base::SsaDefinition v, VarAccess va |
|
||||
instanceofDisjunction(bb, v) and
|
||||
bb.dominates(va.getBasicBlock()) and
|
||||
va = v.getAUse() and
|
||||
va = v.getARead() and
|
||||
instanceofDisjunct(ioe, bb, v) and
|
||||
t = ioe.getSyntacticCheckedType() and
|
||||
n.asExpr() = va
|
||||
|
||||
@@ -25,7 +25,8 @@ private module BaseSsaStage {
|
||||
predicate backref() {
|
||||
(exists(TLocalVar(_, _)) implies any()) and
|
||||
(exists(any(BaseSsaSourceVariable v).getAnAccess()) implies any()) and
|
||||
(exists(getAUse(_)) implies any())
|
||||
(exists(any(SsaDefinition def).getARead()) implies any()) and
|
||||
(captures(_, _) implies any())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +158,7 @@ private module BaseSsaImpl {
|
||||
|
||||
private import BaseSsaImpl
|
||||
|
||||
private module SsaInput implements SsaImplCommon::InputSig<Location, BasicBlock> {
|
||||
private module SsaImplInput implements SsaImplCommon::InputSig<Location, BasicBlock> {
|
||||
class SourceVariable = BaseSsaSourceVariable;
|
||||
|
||||
/**
|
||||
@@ -189,59 +190,46 @@ private module SsaInput implements SsaImplCommon::InputSig<Location, BasicBlock>
|
||||
}
|
||||
}
|
||||
|
||||
private module Impl = SsaImplCommon::Make<Location, Cfg, SsaInput>;
|
||||
private module Impl = SsaImplCommon::Make<Location, Cfg, SsaImplInput>;
|
||||
|
||||
private module SsaInput implements Impl::SsaInputSig {
|
||||
private import java as J
|
||||
|
||||
class Expr = J::Expr;
|
||||
|
||||
class Parameter = J::Parameter;
|
||||
|
||||
class VariableWrite = J::VariableWrite;
|
||||
|
||||
predicate explicitWrite(VariableWrite w, BasicBlock bb, int i, BaseSsaSourceVariable v) {
|
||||
variableUpdate(v, w.asExpr().getControlFlowNode(), bb, i)
|
||||
or
|
||||
exists(Parameter p, Callable c |
|
||||
c = p.getCallable() and
|
||||
v = TLocalVar(c, p) and
|
||||
w.isParameterInit(p) and
|
||||
c.getBody().getBasicBlock() = bb and
|
||||
i = -1
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module Ssa = Impl::MakeSsa<SsaInput>;
|
||||
|
||||
import Ssa
|
||||
private import Cached
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
cached
|
||||
VarRead getAUse(Impl::Definition def) {
|
||||
BaseSsaStage::ref() and
|
||||
exists(BaseSsaSourceVariable v, BasicBlock bb, int i |
|
||||
Impl::ssaDefReachesRead(v, def, bb, i) and
|
||||
result.getControlFlowNode() = bb.getNode(i) and
|
||||
result = v.getAnAccess()
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate ssaDefReachesEndOfBlock(BasicBlock bb, Impl::Definition def) {
|
||||
Impl::ssaDefReachesEndOfBlock(bb, def, _)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate ssaUpdate(Impl::Definition def, VariableUpdate upd) {
|
||||
exists(BaseSsaSourceVariable v, BasicBlock bb, int i |
|
||||
def.definesAt(v, bb, i) and
|
||||
variableUpdate(v, upd.getControlFlowNode(), bb, i) and
|
||||
getDestVar(upd) = v
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate ssaImplicitInit(Impl::WriteDefinition def) {
|
||||
exists(BaseSsaSourceVariable v, BasicBlock bb, int i |
|
||||
def.definesAt(v, bb, i) and
|
||||
hasEntryDef(v, bb) and
|
||||
i = -1
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `init` is a closure variable that captures the value of `capturedvar`. */
|
||||
cached
|
||||
predicate captures(BaseSsaImplicitInit init, BaseSsaVariable capturedvar) {
|
||||
predicate captures(SsaImplicitEntryDefinition init, SsaDefinition capturedvar) {
|
||||
exists(BasicBlock bb, int i |
|
||||
Impl::ssaDefReachesRead(_, capturedvar, bb, i) and
|
||||
Ssa::ssaDefReachesUncertainRead(_, capturedvar, bb, i) and
|
||||
variableCapture(capturedvar.getSourceVariable(), init.getSourceVariable(), bb, i)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate phiHasInputFromBlock(Impl::PhiNode phi, Impl::Definition inp, BasicBlock bb) {
|
||||
Impl::phiHasInputFromBlock(phi, inp, bb)
|
||||
}
|
||||
|
||||
cached
|
||||
module SsaPublic {
|
||||
/**
|
||||
@@ -277,26 +265,73 @@ private module Cached {
|
||||
|
||||
import SsaPublic
|
||||
|
||||
/** An SSA definition in a closure that captures a variable. */
|
||||
class SsaCapturedDefinition extends SsaImplicitEntryDefinition {
|
||||
SsaCapturedDefinition() { captures(this, _) }
|
||||
|
||||
override string toString() { result = "SSA capture def(" + this.getSourceVariable() + ")" }
|
||||
|
||||
/** Holds if this definition captures the value of `capturedvar`. */
|
||||
predicate captures(SsaDefinition capturedvar) { captures(this, capturedvar) }
|
||||
|
||||
/**
|
||||
* Gets a definition that ultimately defines the captured variable and is not itself a phi node.
|
||||
*/
|
||||
SsaDefinition getAnUltimateCapturedDefinition() {
|
||||
exists(SsaDefinition capturedvar |
|
||||
captures(this, capturedvar) and result = capturedvar.getAnUltimateDefinition()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
deprecated private predicate ssaUpdate(Impl::Definition def, VariableUpdate upd) {
|
||||
exists(BaseSsaSourceVariable v, BasicBlock bb, int i |
|
||||
def.definesAt(v, bb, i) and
|
||||
variableUpdate(v, upd.getControlFlowNode(), bb, i) and
|
||||
getDestVar(upd) = v
|
||||
)
|
||||
}
|
||||
|
||||
deprecated private predicate ssaImplicitInit(Impl::WriteDefinition def) {
|
||||
exists(BaseSsaSourceVariable v, BasicBlock bb, int i |
|
||||
def.definesAt(v, bb, i) and
|
||||
hasEntryDef(v, bb) and
|
||||
i = -1
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `SsaDefinition` instead.
|
||||
*
|
||||
* An SSA variable.
|
||||
*/
|
||||
class BaseSsaVariable extends Impl::Definition {
|
||||
/** Gets the `ControlFlowNode` at which this SSA variable is defined. */
|
||||
ControlFlowNode getCfgNode() {
|
||||
exists(BasicBlock bb, int i | this.definesAt(_, bb, i) and result = bb.getNode(0.maximum(i)))
|
||||
}
|
||||
deprecated class BaseSsaVariable extends Impl::Definition {
|
||||
/**
|
||||
* DEPRECATED: Use `getControlFlowNode()` instead.
|
||||
*
|
||||
* Gets the `ControlFlowNode` at which this SSA variable is defined.
|
||||
*/
|
||||
deprecated ControlFlowNode getCfgNode() { result = this.(SsaDefinition).getControlFlowNode() }
|
||||
|
||||
/** Gets an access of this SSA variable. */
|
||||
VarRead getAUse() { result = getAUse(this) }
|
||||
/**
|
||||
* DEPRECATED: Use `getARead()` instead.
|
||||
*
|
||||
* Gets an access of this SSA variable.
|
||||
*/
|
||||
deprecated VarRead getAUse() { result = this.(SsaDefinition).getARead() }
|
||||
|
||||
/** Holds if this SSA variable is live at the end of `b`. */
|
||||
predicate isLiveAtEndOfBlock(BasicBlock b) { ssaDefReachesEndOfBlock(b, this) }
|
||||
predicate isLiveAtEndOfBlock(BasicBlock b) { this.(SsaDefinition).isLiveAtEndOfBlock(b) }
|
||||
|
||||
/** Gets an input to the phi node defining the SSA variable. */
|
||||
private BaseSsaVariable getAPhiInput() { result = this.(BaseSsaPhiNode).getAPhiInput() }
|
||||
private BaseSsaVariable getAPhiInput() { result = this.(BaseSsaPhiNode).getAnInput() }
|
||||
|
||||
/** Gets a definition in the same callable that ultimately defines this variable and is not itself a phi node. */
|
||||
BaseSsaVariable getAnUltimateLocalDefinition() {
|
||||
/**
|
||||
* DEPRECATED: Use `SsaDefinition::getAnUltimateDefinition()` instead.
|
||||
*
|
||||
* Gets a definition in the same callable that ultimately defines this variable and is not itself a phi node.
|
||||
*/
|
||||
deprecated BaseSsaVariable getAnUltimateLocalDefinition() {
|
||||
result = this.getAPhiInput*() and not result instanceof BaseSsaPhiNode
|
||||
}
|
||||
|
||||
@@ -306,18 +341,27 @@ class BaseSsaVariable extends Impl::Definition {
|
||||
* variable.
|
||||
*/
|
||||
private BaseSsaVariable getAPhiInputOrCapturedVar() {
|
||||
result = this.(BaseSsaPhiNode).getAPhiInput() or
|
||||
result = this.(BaseSsaPhiNode).getAnInput() or
|
||||
this.(BaseSsaImplicitInit).captures(result)
|
||||
}
|
||||
|
||||
/** Gets a definition that ultimately defines this variable and is not itself a phi node. */
|
||||
BaseSsaVariable getAnUltimateDefinition() {
|
||||
/**
|
||||
* DEPRECATED: Use `SsaCapturedDefinition::getAnUltimateCapturedDefinition()`
|
||||
* and/or `SsaDefinition::getAnUltimateDefinition()` instead.
|
||||
*
|
||||
* Gets a definition that ultimately defines this variable and is not itself a phi node.
|
||||
*/
|
||||
deprecated BaseSsaVariable getAnUltimateDefinition() {
|
||||
result = this.getAPhiInputOrCapturedVar*() and not result instanceof BaseSsaPhiNode
|
||||
}
|
||||
}
|
||||
|
||||
/** An SSA variable that is defined by a `VariableUpdate`. */
|
||||
class BaseSsaUpdate extends BaseSsaVariable instanceof Impl::WriteDefinition {
|
||||
/**
|
||||
* DEPRECATED: Use `SsaExplicitWrite` instead.
|
||||
*
|
||||
* An SSA variable that is defined by a `VariableUpdate`.
|
||||
*/
|
||||
deprecated class BaseSsaUpdate extends BaseSsaVariable instanceof Impl::WriteDefinition {
|
||||
BaseSsaUpdate() { ssaUpdate(this, _) }
|
||||
|
||||
/** Gets the `VariableUpdate` defining the SSA variable. */
|
||||
@@ -325,34 +369,46 @@ class BaseSsaUpdate extends BaseSsaVariable instanceof Impl::WriteDefinition {
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `SsaParameterInit` or `SsaCapturedDefinition` instead.
|
||||
*
|
||||
* An SSA variable that is defined by its initial value in the callable. This
|
||||
* includes initial values of parameters, fields, and closure variables.
|
||||
*/
|
||||
class BaseSsaImplicitInit extends BaseSsaVariable instanceof Impl::WriteDefinition {
|
||||
deprecated class BaseSsaImplicitInit extends BaseSsaVariable instanceof Impl::WriteDefinition {
|
||||
BaseSsaImplicitInit() { ssaImplicitInit(this) }
|
||||
|
||||
/** Holds if this is a closure variable that captures the value of `capturedvar`. */
|
||||
predicate captures(BaseSsaVariable capturedvar) { captures(this, capturedvar) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `SsaParameterInit::getParameter()` instead.
|
||||
*
|
||||
* Holds if the SSA variable is a parameter defined by its initial value in the callable.
|
||||
*/
|
||||
predicate isParameterDefinition(Parameter p) {
|
||||
deprecated predicate isParameterDefinition(Parameter p) {
|
||||
this.getSourceVariable() = TLocalVar(p.getCallable(), p) and
|
||||
p.getCallable().getBody().getControlFlowNode() = this.getCfgNode()
|
||||
}
|
||||
}
|
||||
|
||||
/** An SSA phi node. */
|
||||
class BaseSsaPhiNode extends BaseSsaVariable instanceof Impl::PhiNode {
|
||||
/** Gets an input to the phi node defining the SSA variable. */
|
||||
BaseSsaVariable getAPhiInput() { this.hasInputFromBlock(result, _) }
|
||||
/**
|
||||
* DEPRECATED: Use `SsaPhiDefinition` instead.
|
||||
*
|
||||
* An SSA phi node.
|
||||
*/
|
||||
deprecated class BaseSsaPhiNode extends BaseSsaVariable instanceof Impl::PhiNode {
|
||||
/**
|
||||
* DEPRECATED: Use `getAnInput()` instead.
|
||||
*
|
||||
* Gets an input to the phi node defining the SSA variable.
|
||||
*/
|
||||
deprecated BaseSsaVariable getAPhiInput() { this.hasInputFromBlock(result, _) }
|
||||
|
||||
/** Gets an input to the phi node defining the SSA variable. */
|
||||
BaseSsaVariable getAnInput() { this.hasInputFromBlock(result, _) }
|
||||
|
||||
/** Holds if `inp` is an input to the phi node along the edge originating in `bb`. */
|
||||
predicate hasInputFromBlock(BaseSsaVariable inp, BasicBlock bb) {
|
||||
phiHasInputFromBlock(this, inp, bb)
|
||||
this.(SsaPhiDefinition).hasInputFromBlock(inp, bb)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import java
|
||||
private import VirtualDispatch
|
||||
private import semmle.code.java.dataflow.internal.BaseSSA
|
||||
private import semmle.code.java.dataflow.internal.BaseSSA as Base
|
||||
private import semmle.code.java.dataflow.internal.DataFlowUtil as DataFlow
|
||||
private import semmle.code.java.dataflow.internal.DataFlowPrivate as DataFlowPrivate
|
||||
private import semmle.code.java.dataflow.InstanceAccess
|
||||
@@ -162,14 +162,28 @@ private module TypeTrackingSteps {
|
||||
storeContents = loadContents
|
||||
}
|
||||
|
||||
predicate simpleLocalSmallStep(Node n1, Node n2) {
|
||||
exists(BaseSsaVariable v, BaseSsaVariable def |
|
||||
def.(BaseSsaUpdate).getDefiningExpr().(VariableAssign).getSource() = n1.asExpr()
|
||||
or
|
||||
def.(BaseSsaImplicitInit).isParameterDefinition(n1.asParameter())
|
||||
/**
|
||||
* Holds if `n` is a read of an SSA variable that is ultimately defined by `def`.
|
||||
*
|
||||
* This includes reads of captured variables even though they are not technically
|
||||
* local steps, but treating them as local is useful for type tracking purposes.
|
||||
*/
|
||||
private predicate readsSsa(Node n, Base::SsaDefinition def) {
|
||||
exists(Base::SsaDefinition v |
|
||||
v.getAnUltimateDefinition() = def or
|
||||
v.(Base::SsaCapturedDefinition).getAnUltimateCapturedDefinition() = def
|
||||
|
|
||||
v.getAnUltimateDefinition() = def and
|
||||
v.getAUse() = n2.asExpr()
|
||||
v.getARead() = n.asExpr()
|
||||
)
|
||||
}
|
||||
|
||||
predicate simpleLocalSmallStep(Node n1, Node n2) {
|
||||
exists(Base::SsaDefinition def |
|
||||
def.(Base::SsaExplicitWrite).getDefiningExpr().(VariableAssign).getSource() = n1.asExpr()
|
||||
or
|
||||
def.(Base::SsaParameterInit).getParameter() = n1.asParameter()
|
||||
|
|
||||
readsSsa(n2, def)
|
||||
)
|
||||
or
|
||||
exists(Callable c | n1.(DataFlow::InstanceParameterNode).getCallable() = c |
|
||||
@@ -220,11 +234,10 @@ private module TypeTrackingSteps {
|
||||
n2.asExpr() = get
|
||||
)
|
||||
or
|
||||
exists(EnhancedForStmt for, BaseSsaVariable ssa, BaseSsaVariable def |
|
||||
for.getVariable() = def.(BaseSsaUpdate).getDefiningExpr() and
|
||||
exists(EnhancedForStmt for, Base::SsaDefinition def |
|
||||
for.getVariable() = def.(Base::SsaExplicitWrite).getDefiningExpr() and
|
||||
for.getExpr() = v.getAnAccess() and
|
||||
ssa.getAnUltimateDefinition() = def and
|
||||
ssa.getAUse() = n2.asExpr()
|
||||
readsSsa(n2, def)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -259,16 +272,15 @@ private module TypeTrackingSteps {
|
||||
}
|
||||
|
||||
predicate loadStep(Node n1, LocalSourceNode n2, Content f) {
|
||||
exists(BaseSsaVariable v, BaseSsaVariable def |
|
||||
exists(Base::SsaDefinition def |
|
||||
exists(EnhancedForStmt for |
|
||||
for.getVariable() = def.(BaseSsaUpdate).getDefiningExpr() and
|
||||
for.getVariable() = def.(Base::SsaExplicitWrite).getDefiningExpr() and
|
||||
for.getExpr() = n1.asExpr() and
|
||||
n1.getType() instanceof Array and
|
||||
f = ContentArray()
|
||||
)
|
||||
|
|
||||
v.getAnUltimateDefinition() = def and
|
||||
v.getAUse() = n2.asExpr()
|
||||
readsSsa(n2, def)
|
||||
)
|
||||
or
|
||||
n2.asExpr().(ArrayAccess).getArray() = n1.asExpr()
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
import java
|
||||
private import VirtualDispatch
|
||||
private import semmle.code.java.controlflow.Guards
|
||||
private import semmle.code.java.dataflow.internal.BaseSSA
|
||||
private import semmle.code.java.dataflow.internal.BaseSSA as Base
|
||||
private import semmle.code.java.dataflow.internal.DataFlowUtil
|
||||
private import semmle.code.java.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.java.dataflow.internal.ContainerFlow
|
||||
@@ -71,21 +71,24 @@ private predicate callFlowStep(Node n1, Node n2) {
|
||||
* flow, calls, returns, fields, array reads or writes, or container taint steps.
|
||||
*/
|
||||
private predicate step(Node n1, Node n2) {
|
||||
exists(BaseSsaVariable v, BaseSsaVariable def |
|
||||
def.(BaseSsaUpdate).getDefiningExpr().(VariableAssign).getSource() = n1.asExpr()
|
||||
exists(Base::SsaDefinition v, Base::SsaDefinition def |
|
||||
def.(Base::SsaExplicitWrite).getDefiningExpr().(VariableAssign).getSource() = n1.asExpr()
|
||||
or
|
||||
def.(BaseSsaImplicitInit).isParameterDefinition(n1.asParameter())
|
||||
def.(Base::SsaParameterInit).getParameter() = n1.asParameter()
|
||||
or
|
||||
exists(EnhancedForStmt for |
|
||||
for.getVariable() = def.(BaseSsaUpdate).getDefiningExpr() and
|
||||
for.getVariable() = def.(Base::SsaExplicitWrite).getDefiningExpr() and
|
||||
for.getExpr() = n1.asExpr()
|
||||
)
|
||||
|
|
||||
v.getAnUltimateDefinition() = def and
|
||||
v.getAUse() = n2.asExpr()
|
||||
(
|
||||
v.(Base::SsaCapturedDefinition).getAnUltimateCapturedDefinition() = def or
|
||||
v.getAnUltimateDefinition() = def
|
||||
) and
|
||||
v.getARead() = n2.asExpr()
|
||||
)
|
||||
or
|
||||
baseSsaAdjacentUseUse(n1.asExpr(), n2.asExpr())
|
||||
Base::baseSsaAdjacentUseUse(n1.asExpr(), n2.asExpr())
|
||||
or
|
||||
exists(Callable c | n1.(InstanceParameterNode).getCallable() = c |
|
||||
exists(InstanceAccess ia |
|
||||
|
||||
@@ -7,7 +7,7 @@ import java
|
||||
import semmle.code.java.dataflow.TypeFlow
|
||||
private import DispatchFlow as DispatchFlow
|
||||
private import ObjFlow as ObjFlow
|
||||
private import semmle.code.java.dataflow.internal.BaseSSA
|
||||
private import semmle.code.java.dataflow.internal.BaseSSA as Base
|
||||
private import semmle.code.java.controlflow.Guards
|
||||
private import semmle.code.java.dispatch.internal.Unification
|
||||
|
||||
@@ -194,10 +194,10 @@ private module Dispatch {
|
||||
*/
|
||||
private predicate impossibleDispatchTarget(MethodCall source, Method tgt) {
|
||||
tgt = viableImpl_v1_cand(source) and
|
||||
exists(Guard typeTest, BaseSsaVariable v, Expr q, RefType t |
|
||||
exists(Guard typeTest, Base::SsaDefinition v, Expr q, RefType t |
|
||||
source.getQualifier() = q and
|
||||
v.getAUse() = q and
|
||||
typeTest.appliesTypeTest(v.getAUse(), t, false) and
|
||||
v.getARead() = q and
|
||||
typeTest.appliesTypeTest(v.getARead(), t, false) and
|
||||
guardControls_v1(typeTest, q.getBasicBlock(), false) and
|
||||
tgt.getDeclaringType().getSourceDeclaration().getASourceSupertype*() = t.getErasure()
|
||||
)
|
||||
|
||||
@@ -262,10 +262,10 @@ private predicate reaches(Expr src, Argument arg) {
|
||||
any(StartComponentMethodCall ma).getIntentArg() = arg and
|
||||
src = arg
|
||||
or
|
||||
exists(Expr mid, BaseSsa::BaseSsaVariable ssa, BaseSsa::BaseSsaUpdate upd |
|
||||
exists(Expr mid, BaseSsa::SsaDefinition ssa, BaseSsa::SsaExplicitWrite upd |
|
||||
reaches(mid, arg) and
|
||||
mid = ssa.getAUse() and
|
||||
upd = ssa.getAnUltimateLocalDefinition() and
|
||||
mid = ssa.getARead() and
|
||||
upd = ssa.getAnUltimateDefinition() and
|
||||
src = upd.getDefiningExpr().(VariableAssign).getSource()
|
||||
)
|
||||
or
|
||||
|
||||
@@ -9,7 +9,7 @@ import java
|
||||
private import codeql.typeflow.UniversalFlow as UniversalFlow
|
||||
private import semmle.code.java.Collections
|
||||
private import semmle.code.java.controlflow.Guards
|
||||
private import semmle.code.java.dataflow.internal.BaseSSA
|
||||
private import semmle.code.java.dataflow.internal.BaseSSA as Base
|
||||
private import semmle.code.java.dataflow.TaintTracking
|
||||
private import semmle.code.java.dataflow.TypeFlow
|
||||
private import semmle.code.java.dispatch.VirtualDispatch
|
||||
@@ -115,7 +115,7 @@ private predicate nodeWithAddition(FlowNode n, Variable v) {
|
||||
n.asField() = v
|
||||
or
|
||||
n.asSsa().getSourceVariable().getVariable() = v and
|
||||
(n.asSsa() instanceof BaseSsaUpdate or n.asSsa().(BaseSsaImplicitInit).isParameterDefinition(_))
|
||||
n.asSsa() instanceof Base::SsaExplicitWrite
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user