mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Java: Introduce SsaCapturedDefinition and replace uses of getAnUltimateDefinition.
This commit is contained in:
@@ -34,8 +34,12 @@ predicate useUsePair(VarRead use1, VarRead use2) { adjacentUseUse+(use1, use2) }
|
|||||||
* Other paths may also exist, so the SSA variables in `def` and `use` can be different.
|
* Other paths may also exist, so the SSA variables in `def` and `use` can be different.
|
||||||
*/
|
*/
|
||||||
predicate defUsePair(VariableUpdate def, VarRead use) {
|
predicate defUsePair(VariableUpdate def, VarRead use) {
|
||||||
exists(SsaVariable v |
|
exists(SsaDefinition v, SsaExplicitWrite write |
|
||||||
v.getAUse() = use and v.getAnUltimateDefinition().(SsaExplicitWrite).getDefiningExpr() = def
|
v.getARead() = use and write.getDefiningExpr() = def
|
||||||
|
|
|
||||||
|
v.getAnUltimateDefinition() = write
|
||||||
|
or
|
||||||
|
v.(SsaCapturedDefinition).getAnUltimateCapturedDefinition() = write
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +50,9 @@ predicate defUsePair(VariableUpdate def, VarRead use) {
|
|||||||
* Other paths may also exist, so the SSA variables can be different.
|
* Other paths may also exist, so the SSA variables can be different.
|
||||||
*/
|
*/
|
||||||
predicate parameterDefUsePair(Parameter p, VarRead use) {
|
predicate parameterDefUsePair(Parameter p, VarRead use) {
|
||||||
exists(SsaVariable v |
|
exists(SsaDefinition v, SsaParameterInit init | v.getARead() = use and init.getParameter() = p |
|
||||||
v.getAUse() = use and v.getAnUltimateDefinition().(SsaParameterInit).getParameter() = p
|
v.getAnUltimateDefinition() = init
|
||||||
|
or
|
||||||
|
v.(SsaCapturedDefinition).getAnUltimateCapturedDefinition() = init
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,8 +120,8 @@ predicate clearlyNotNull(SsaVariable v, Expr reason) {
|
|||||||
reason = decl
|
reason = decl
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(SsaVariable captured |
|
exists(SsaDefinition captured |
|
||||||
v.(SsaImplicitInit).captures(captured) and
|
v.(SsaCapturedDefinition).captures(captured) and
|
||||||
clearlyNotNull(captured, reason)
|
clearlyNotNull(captured, reason)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
|
|||||||
@@ -278,8 +278,8 @@ predicate nullDeref(SsaSourceVariable v, VarAccess va, string msg, Expr reason)
|
|||||||
* A dereference of a variable that is always `null`.
|
* A dereference of a variable that is always `null`.
|
||||||
*/
|
*/
|
||||||
predicate alwaysNullDeref(SsaSourceVariable v, VarAccess va) {
|
predicate alwaysNullDeref(SsaSourceVariable v, VarAccess va) {
|
||||||
exists(BasicBlock bb, SsaVariable ssa |
|
exists(BasicBlock bb, SsaDefinition ssa |
|
||||||
forall(SsaVariable def | def = ssa.getAnUltimateDefinition() |
|
forall(SsaDefinition def | def = ssa.getAnUltimateDefinition() |
|
||||||
def.(SsaExplicitWrite).getValue() = alwaysNullExpr()
|
def.(SsaExplicitWrite).getValue() = alwaysNullExpr()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
|
|||||||
@@ -140,6 +140,25 @@ class SsaSourceField extends SsaSourceVariable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 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()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an access of the SSA source variable underlying this SSA variable
|
* Gets an access of the SSA source variable underlying this SSA variable
|
||||||
* that can be reached from this SSA variable without passing through any
|
* that can be reached from this SSA variable without passing through any
|
||||||
@@ -194,18 +213,25 @@ class SsaVariable extends Definition {
|
|||||||
predicate isLiveAtEndOfBlock(BasicBlock b) { ssaDefReachesEndOfBlock(b, this) }
|
predicate isLiveAtEndOfBlock(BasicBlock b) { ssaDefReachesEndOfBlock(b, this) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* DEPRECATED.
|
||||||
|
*
|
||||||
* Gets an SSA variable whose value can flow to this one in one step. This
|
* Gets an SSA variable whose value can flow to this one in one step. This
|
||||||
* includes inputs to phi nodes, the prior definition of uncertain updates,
|
* includes inputs to phi nodes, the prior definition of uncertain updates,
|
||||||
* and the captured ssa variable for a closure variable.
|
* and the captured ssa variable for a closure variable.
|
||||||
*/
|
*/
|
||||||
SsaVariable getAPhiInputOrPriorDef() {
|
deprecated SsaVariable getAPhiInputOrPriorDef() {
|
||||||
result = this.(SsaPhiNode).getAPhiInput() or
|
result = this.(SsaPhiNode).getAPhiInput() or
|
||||||
result = this.(SsaUncertainImplicitUpdate).getPriorDef() or
|
result = this.(SsaUncertainImplicitUpdate).getPriorDef() or
|
||||||
this.(SsaImplicitInit).captures(result)
|
this.(SsaImplicitInit).captures(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a definition that ultimately defines this variable and is not itself a phi node. */
|
/**
|
||||||
SsaVariable 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 SsaVariable getAnUltimateDefinition() {
|
||||||
result = this.getAPhiInputOrPriorDef*() and not result instanceof SsaPhiNode
|
result = this.getAPhiInputOrPriorDef*() and not result instanceof SsaPhiNode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -319,6 +345,8 @@ class SsaUncertainImplicitUpdate extends SsaImplicitUpdate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* DEPRECATED: Use `SsaParameterInit`, `SsaImplicitEntryDefinition`, or `SsaCapturedDefinition` instead.
|
||||||
|
*
|
||||||
* An SSA variable that is defined by its initial value in the callable. This
|
* An SSA variable that is defined by its initial value in the callable. This
|
||||||
* includes initial values of parameters, fields, and closure variables.
|
* includes initial values of parameters, fields, and closure variables.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -62,9 +62,10 @@ private predicate fieldStep(Node node1, Node node2) {
|
|||||||
private predicate closureFlowStep(Expr e1, Expr e2) {
|
private predicate closureFlowStep(Expr e1, Expr e2) {
|
||||||
simpleAstFlowStep(e1, e2)
|
simpleAstFlowStep(e1, e2)
|
||||||
or
|
or
|
||||||
exists(SsaVariable v |
|
exists(SsaDefinition v, SsaExplicitWrite def | v.getARead() = e2 and def.getValue() = e1 |
|
||||||
v.getAUse() = e2 and
|
v.getAnUltimateDefinition() = def
|
||||||
v.getAnUltimateDefinition().(SsaExplicitWrite).getValue() = e1
|
or
|
||||||
|
v.(SsaCapturedDefinition).getAnUltimateCapturedDefinition() = def
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,9 @@ predicate localExprFlow(Expr e1, Expr e2) { localFlow(exprNode(e1), exprNode(e2)
|
|||||||
predicate hasNonlocalValue(FieldRead fr) {
|
predicate hasNonlocalValue(FieldRead fr) {
|
||||||
not exists(SsaVariable v | v.getAUse() = fr)
|
not exists(SsaVariable v | v.getAUse() = fr)
|
||||||
or
|
or
|
||||||
exists(SsaVariable v, SsaVariable def | v.getAUse() = fr and def = v.getAnUltimateDefinition() |
|
exists(SsaDefinition v, SsaDefinition def |
|
||||||
|
v.getARead() = fr and def = v.getAnUltimateDefinition()
|
||||||
|
|
|
||||||
def instanceof SsaImplicitInit or
|
def instanceof SsaImplicitInit or
|
||||||
def instanceof SsaImplicitUpdate
|
def instanceof SsaImplicitUpdate
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -41,7 +41,9 @@ private class InputStreamWrapperCapturedJumpStep extends AdditionalTaintStep {
|
|||||||
*/
|
*/
|
||||||
private class InputStreamWrapperCapturedLocalStep extends AdditionalTaintStep {
|
private class InputStreamWrapperCapturedLocalStep extends AdditionalTaintStep {
|
||||||
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||||
exists(InputStreamRead m, NestedClass wrapper, SsaVariable captured, SsaImplicitInit capturer |
|
exists(
|
||||||
|
InputStreamRead m, NestedClass wrapper, SsaDefinition captured, SsaCapturedDefinition capturer
|
||||||
|
|
|
||||||
wrapper.getASourceSupertype+() instanceof TypeInputStream and
|
wrapper.getASourceSupertype+() instanceof TypeInputStream and
|
||||||
m.getDeclaringType() = wrapper and
|
m.getDeclaringType() = wrapper and
|
||||||
capturer.captures(captured) and
|
capturer.captures(captured) and
|
||||||
|
|||||||
@@ -38,9 +38,13 @@ private predicate isShell(Expr ex) {
|
|||||||
cmd.regexpMatch(".*(sh|javac?|python[23]?|osascript|cmd)(\\.exe)?$")
|
cmd.regexpMatch(".*(sh|javac?|python[23]?|osascript|cmd)(\\.exe)?$")
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(SsaVariable ssa |
|
exists(SsaDefinition ssa, SsaExplicitWrite def |
|
||||||
ex = ssa.getAUse() and
|
ex = ssa.getARead() and
|
||||||
isShell(ssa.getAnUltimateDefinition().(SsaExplicitWrite).getDefiningExpr())
|
isShell(def.getDefiningExpr())
|
||||||
|
|
|
||||||
|
ssa.getAnUltimateDefinition() = def
|
||||||
|
or
|
||||||
|
ssa.(SsaCapturedDefinition).getAnUltimateCapturedDefinition() = def
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
isShell(ex.(Assignment).getRhs())
|
isShell(ex.(Assignment).getRhs())
|
||||||
|
|||||||
@@ -277,10 +277,7 @@ private module SinkModelGeneratorInput implements SinkModelGeneratorInputSig {
|
|||||||
|
|
||||||
predicate sinkModelSanitizer(DataFlow::Node node) {
|
predicate sinkModelSanitizer(DataFlow::Node node) {
|
||||||
// exclude variable capture jump steps
|
// exclude variable capture jump steps
|
||||||
exists(Ssa::SsaImplicitInit closure |
|
exists(Ssa::SsaCapturedDefinition closure | node.asExpr() = Ssa::ssaGetAFirstUse(closure))
|
||||||
closure.captures(_) and
|
|
||||||
node.asExpr() = Ssa::ssaGetAFirstUse(closure)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate apiSource(DataFlow::Node source) {
|
predicate apiSource(DataFlow::Node source) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import java
|
import java
|
||||||
import semmle.code.java.dataflow.SSA
|
import semmle.code.java.dataflow.SSA
|
||||||
|
|
||||||
from SsaImplicitInit closure, SsaVariable captured
|
from SsaCapturedDefinition closure, SsaDefinition captured
|
||||||
where closure.captures(captured)
|
where closure.captures(captured)
|
||||||
select closure, captured
|
select closure, captured
|
||||||
|
|||||||
Reference in New Issue
Block a user