Java: Replace BaseSSA class wrappers with shared code.

This commit is contained in:
Anders Schack-Mulligen
2025-10-23 13:54:27 +02:00
parent 551944bacb
commit 942dc2b89e
8 changed files with 206 additions and 155 deletions

View File

@@ -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;

View File

@@ -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

View File

@@ -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)
}
}

View File

@@ -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()

View File

@@ -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 |

View File

@@ -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()
)

View File

@@ -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

View File

@@ -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
)
}