Merge branch 'main' into jorgectf/deserialization-lookahead

This commit is contained in:
Jorge
2023-06-23 18:24:39 +02:00
committed by GitHub
1972 changed files with 63527 additions and 26995 deletions

View File

@@ -1809,9 +1809,6 @@ class LValue extends VarAccess {
* are source expressions of the assignment.
*/
Expr getRhs() { exists(Assignment e | e.getDest() = this and e.getSource() = result) }
/** DEPRECATED: Alias for getRhs */
deprecated Expr getRHS() { result = this.getRhs() }
}
/**

View File

@@ -987,6 +987,17 @@ private string getAPublicObjectMethodSignature() {
)
}
pragma[nomagic]
private predicate interfaceInheritsOverridingNonAbstractMethod(Interface interface, Method m) {
interface.inherits(m) and
not m.isAbstract() and
m.overrides(_)
}
bindingset[m]
pragma[inline_late]
private Method getAnOverridden(Method m) { m.overrides(result) }
private Method getAnAbstractMethod(Interface interface) {
interface.inherits(result) and
result.isAbstract() and
@@ -995,9 +1006,8 @@ private Method getAnAbstractMethod(Interface interface) {
// Make sure that there is no other non-abstract method
// (e.g. `default`) which overrides the abstract one
not exists(Method m |
interface.inherits(m) and
not m.isAbstract() and
m.overrides(result)
interfaceInheritsOverridingNonAbstractMethod(interface, m) and
result = getAnOverridden(m)
)
}

View File

@@ -6,15 +6,6 @@
import java
/**
* DEPRECATED: Use `conditionCheckMethodArgument` instead.
* Holds if `m` is a non-overridable method that checks that its first argument
* is equal to `checkTrue` and throws otherwise.
*/
deprecated predicate conditionCheckMethod(Method m, boolean checkTrue) {
conditionCheckMethodArgument(m, 0, checkTrue)
}
/**
* Holds if `m` is a non-overridable method that checks that its zero-indexed `argument`
* is equal to `checkTrue` and throws otherwise.

View File

@@ -87,6 +87,7 @@ private import internal.FlowSummaryImplSpecific as FlowSummaryImplSpecific
private import internal.AccessPathSyntax
private import ExternalFlowExtensions as Extensions
private import FlowSummary
private import codeql.mad.ModelValidation as SharedModelVal
/**
* A class for activating additional model rows.
@@ -265,38 +266,18 @@ module ModelValidation {
)
}
private string getInvalidModelKind() {
exists(string kind | summaryModel(_, _, _, _, _, _, _, _, kind, _) |
not kind = ["taint", "value"] and
result = "Invalid kind \"" + kind + "\" in summary model."
)
or
exists(string kind | sinkModel(_, _, _, _, _, _, _, kind, _) |
not kind =
[
"open-url", "jndi-injection", "ldap", "sql", "jdbc-url", "logging", "mvel", "xpath",
"groovy", "xss", "ognl-injection", "intent-start", "pending-intent-sent", "url-redirect",
"create-file", "read-file", "write-file", "set-hostname-verifier", "header-splitting",
"information-leak", "xslt", "jexl", "bean-validation", "ssti", "fragment-injection",
"command-injection"
] and
not kind.matches("regex-use%") and
not kind.matches("qltest%") and
result = "Invalid kind \"" + kind + "\" in sink model."
)
or
exists(string kind | sourceModel(_, _, _, _, _, _, _, kind, _) |
not kind = ["remote", "contentprovider", "android-widget", "android-external-storage-dir"] and
not kind.matches("qltest%") and
result = "Invalid kind \"" + kind + "\" in source model."
)
or
exists(string kind | neutralModel(_, _, _, _, kind, _) |
not kind = ["summary", "source", "sink"] and
result = "Invalid kind \"" + kind + "\" in neutral model."
)
private module KindValConfig implements SharedModelVal::KindValidationConfigSig {
predicate summaryKind(string kind) { summaryModel(_, _, _, _, _, _, _, _, kind, _) }
predicate sinkKind(string kind) { sinkModel(_, _, _, _, _, _, _, kind, _) }
predicate sourceKind(string kind) { sourceModel(_, _, _, _, _, _, _, kind, _) }
predicate neutralKind(string kind) { neutralModel(_, _, _, _, kind, _) }
}
private module KindVal = SharedModelVal::KindValidation<KindValConfig>;
private string getInvalidModelSignature() {
exists(
string pred, string package, string type, string name, string signature, string ext,
@@ -338,7 +319,7 @@ module ModelValidation {
msg =
[
getInvalidModelSignature(), getInvalidModelInput(), getInvalidModelOutput(),
getInvalidModelKind()
KindVal::getInvalidModelKind()
]
}
}

View File

@@ -37,10 +37,11 @@ abstract class RemoteFlowSource extends DataFlow::Node {
}
/**
* A module for importing frameworks that define remote flow sources.
* A module for importing frameworks that define flow sources.
*/
private module RemoteFlowSources {
private import semmle.code.java.frameworks.android.Widget
private module FlowSources {
private import semmle.code.java.frameworks.hudson.Hudson
private import semmle.code.java.frameworks.stapler.Stapler
}
private class ExternalRemoteFlowSource extends RemoteFlowSource {

View File

@@ -23,6 +23,7 @@ private module Frameworks {
private import semmle.code.java.frameworks.Properties
private import semmle.code.java.frameworks.Protobuf
private import semmle.code.java.frameworks.ratpack.RatpackExec
private import semmle.code.java.frameworks.stapler.Stapler
private import semmle.code.java.JDK
}

View File

@@ -149,8 +149,9 @@ class SummarizedCallableBase extends TSummarizedCallableBase {
or
result = this.asSyntheticCallable().getParameterType(pos)
or
exists(SyntheticCallable sc | sc = this.asSyntheticCallable() |
Impl::Private::summaryParameterNodeRange(this, pos) and
exists(SyntheticCallable sc, Impl::Private::SummaryNode p | sc = this.asSyntheticCallable() |
Impl::Private::summaryParameterNode(p, pos) and
this = p.getSummarizedCallable() and
not exists(sc.getParameterType(pos)) and
result instanceof TypeObject
)

View File

@@ -931,9 +931,6 @@ class SsaVariable extends TSsaVariable {
this = TSsaUntracked(_, result)
}
/** DEPRECATED: Alias for getCfgNode */
deprecated ControlFlowNode getCFGNode() { result = this.getCfgNode() }
/** Gets a textual representation of this SSA variable. */
string toString() { none() }

View File

@@ -483,9 +483,6 @@ class BaseSsaVariable extends TBaseSsaVariable {
this = TSsaEntryDef(_, result)
}
/** DEPRECATED: Alias for getCfgNode */
deprecated ControlFlowNode getCFGNode() { result = this.getCfgNode() }
string toString() { none() }
Location getLocation() { result = this.getCfgNode().getLocation() }

View File

@@ -1135,8 +1135,8 @@ module Impl<FullStateConfigSig Config> {
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow
);
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap);
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t);
bindingset[typ, contentType]
predicate typecheckStore(Typ typ, DataFlowType contentType);
@@ -1199,17 +1199,21 @@ module Impl<FullStateConfigSig Config> {
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t, Ap ap, ApApprox apa
) {
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t, ap, apa) and
PrevStage::revFlow(node, state, apa) and
filter(node, state, t, ap)
fwdFlow1(node, state, cc, summaryCtx, argT, argAp, _, t, ap, apa)
}
pragma[inline]
additional predicate fwdFlow(
private predicate fwdFlow1(
NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t, Ap ap
ApOption argAp, Typ t0, Typ t, Ap ap, ApApprox apa
) {
fwdFlow(node, state, cc, summaryCtx, argT, argAp, t, ap, _)
fwdFlow0(node, state, cc, summaryCtx, argT, argAp, t0, ap, apa) and
PrevStage::revFlow(node, state, apa) and
filter(node, state, t0, ap, t)
}
pragma[nomagic]
private predicate typeStrengthen(Typ t0, Ap ap, Typ t) {
fwdFlow1(_, _, _, _, _, _, t0, t, ap, _) and t0 != t
}
pragma[assume_small_delta]
@@ -1339,6 +1343,11 @@ module Impl<FullStateConfigSig Config> {
private predicate fwdFlowConsCand(Typ t2, Ap cons, Content c, Typ t1, Ap tail) {
fwdFlowStore(_, t1, tail, c, t2, _, _, _, _, _, _) and
cons = apCons(c, t1, tail)
or
exists(Typ t0 |
typeStrengthen(t0, cons, t2) and
fwdFlowConsCand(t0, cons, c, t1, tail)
)
}
pragma[nomagic]
@@ -1359,7 +1368,7 @@ module Impl<FullStateConfigSig Config> {
ParamNodeOption summaryCtx, TypOption argT, ApOption argAp
) {
exists(ApHeadContent apc |
fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap) and
fwdFlow(node1, state, cc, summaryCtx, argT, argAp, t, ap, _) and
apc = getHeadContent(ap) and
readStepCand0(node1, apc, c, node2)
)
@@ -1520,14 +1529,14 @@ module Impl<FullStateConfigSig Config> {
NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap
) {
revFlow0(node, state, returnCtx, returnAp, ap) and
fwdFlow(node, state, _, _, _, _, _, ap)
fwdFlow(node, state, _, _, _, _, _, ap, _)
}
pragma[nomagic]
private predicate revFlow0(
NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap
) {
fwdFlow(node, state, _, _, _, _, _, ap) and
fwdFlow(node, state, _, _, _, _, _, ap, _) and
sinkNode(node, state) and
(
if hasSinkCallCtx()
@@ -1780,13 +1789,13 @@ module Impl<FullStateConfigSig Config> {
boolean fwd, int nodes, int fields, int conscand, int states, int tuples
) {
fwd = true and
nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _)) and
nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, _, _, _)) and
fields = count(Content f0 | fwdConsCand(f0, _, _)) and
conscand = count(Content f0, Typ t, Ap ap | fwdConsCand(f0, t, ap)) and
states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _)) and
states = count(FlowState state | fwdFlow(_, state, _, _, _, _, _, _, _)) and
tuples =
count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, TypOption argT,
ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap))
ApOption argAp, Typ t, Ap ap | fwdFlow(n, state, cc, summaryCtx, argT, argAp, t, ap, _))
or
fwd = false and
nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and
@@ -1963,10 +1972,10 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
PrevStage::revFlowState(state) and
exists(t) and
t0 = t and
exists(ap) and
not stateBarrier(node, state) and
(
@@ -2012,7 +2021,8 @@ module Impl<FullStateConfigSig Config> {
FlowCheckNode() {
castNode(this.asNode()) or
clearsContentCached(this.asNode(), _) or
expectsContentCached(this.asNode(), _)
expectsContentCached(this.asNode(), _) or
neverSkipInPathGraph(this.asNode())
}
}
@@ -2197,8 +2207,8 @@ module Impl<FullStateConfigSig Config> {
import BooleanCallContext
predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, LocalCc lcc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
exists(lcc)
@@ -2218,10 +2228,16 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
exists(state) and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
// We can get away with not using type strengthening here, since we aren't
// going to use the tracked types in the construction of Stage 4 access
// paths. For Stage 4 and onwards, the tracked types must be consistent as
// the cons candidates including types are used to construct subsequent
// access path approximations.
t0 = t and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t0) else any()) and
(
notExpectsContent(node)
or
@@ -2241,6 +2257,16 @@ module Impl<FullStateConfigSig Config> {
import MkStage<Stage2>::Stage<Stage3Param>
}
bindingset[node, t0]
private predicate strengthenType(NodeEx node, DataFlowType t0, DataFlowType t) {
if castingNodeEx(node)
then
exists(DataFlowType nt | nt = node.getDataFlowType() |
if typeStrongerThan(nt, t0) then t = nt else (compatibleTypes(nt, t0) and t = t0)
)
else t = t0
}
private module Stage4Param implements MkStage<Stage3>::StageParam {
private module PrevStage = Stage3;
@@ -2274,8 +2300,8 @@ module Impl<FullStateConfigSig Config> {
pragma[nomagic]
predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, LocalCc lcc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, _) and
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
@@ -2333,11 +2359,11 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
exists(state) and
not clear(node, ap) and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
strengthenType(node, t0, t) and
(
notExpectsContent(node)
or
@@ -2365,7 +2391,7 @@ module Impl<FullStateConfigSig Config> {
exists(AccessPathFront apf |
Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and
Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, _, TAccessPathFrontSome(argApf), _,
apf)
apf, _)
)
}
@@ -2579,8 +2605,8 @@ module Impl<FullStateConfigSig Config> {
import LocalCallContext
predicate localStep(
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
DataFlowType t, LocalCc lcc
NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, Typ t,
LocalCc lcc
) {
localFlowBigStep(node1, state1, node2, state2, preservesValue, t, lcc) and
PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and
@@ -2609,9 +2635,9 @@ module Impl<FullStateConfigSig Config> {
)
}
bindingset[node, state, t, ap]
predicate filter(NodeEx node, FlowState state, Typ t, Ap ap) {
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any()) and
bindingset[node, state, t0, ap]
predicate filter(NodeEx node, FlowState state, Typ t0, Ap ap, Typ t) {
strengthenType(node, t0, t) and
exists(state) and
exists(ap)
}
@@ -2632,7 +2658,7 @@ module Impl<FullStateConfigSig Config> {
Stage5::parameterMayFlowThrough(p, _) and
Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and
Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), _,
TAccessPathApproxSome(apa), _, apa0)
TAccessPathApproxSome(apa), _, apa0, _)
)
}
@@ -2649,7 +2675,7 @@ module Impl<FullStateConfigSig Config> {
TSummaryCtxSome(ParamNodeEx p, FlowState state, DataFlowType t, AccessPath ap) {
exists(AccessPathApprox apa | ap.getApprox() = apa |
Stage5::parameterMayFlowThrough(p, apa) and
Stage5::fwdFlow(p, state, _, _, _, _, t, apa) and
Stage5::fwdFlow(p, state, _, _, Option<DataFlowType>::some(t), _, _, apa, _) and
Stage5::revFlow(p, state, _)
)
}
@@ -2820,9 +2846,7 @@ module Impl<FullStateConfigSig Config> {
ap = TAccessPathNil()
or
// ... or a step from an existing PathNode to another node.
pathStep(_, node, state, cc, sc, t, ap) and
Stage5::revFlow(node, state, ap.getApprox()) and
(if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), t) else any())
pathStep(_, node, state, cc, sc, t, ap)
} or
TPathNodeSink(NodeEx node, FlowState state) {
exists(PathNodeMid sink |
@@ -3340,13 +3364,24 @@ module Impl<FullStateConfigSig Config> {
ap = mid.getAp()
}
private predicate pathStep(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
AccessPath ap
) {
exists(DataFlowType t0 |
pathStep0(mid, node, state, cc, sc, t0, ap) and
Stage5::revFlow(node, state, ap.getApprox()) and
strengthenType(node, t0, t)
)
}
/**
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
pragma[assume_small_delta]
pragma[nomagic]
private predicate pathStep(
private predicate pathStep0(
PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, DataFlowType t,
AccessPath ap
) {
@@ -3964,7 +3999,7 @@ module Impl<FullStateConfigSig Config> {
ap = TPartialNil() and
exists(explorationLimit())
or
partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
distSrc(node.getEnclosingCallable()) <= explorationLimit()
} or
TPartialPathNodeRev(
@@ -3990,11 +4025,20 @@ module Impl<FullStateConfigSig Config> {
}
pragma[nomagic]
private predicate partialPathNodeMk0(
NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
private predicate partialPathStep(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
) {
partialPathStep(_, node, state, cc, sc1, sc2, sc3, sc4, t, ap) and
partialPathStep1(mid, node, state, cc, sc1, sc2, sc3, sc4, _, t, ap)
}
pragma[nomagic]
private predicate partialPathStep1(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t0, DataFlowType t,
PartialAccessPath ap
) {
partialPathStep0(mid, node, state, cc, sc1, sc2, sc3, sc4, t0, ap) and
not fullBarrier(node) and
not stateBarrier(node, state) and
not clearsContentEx(node, ap.getHead()) and
@@ -4002,9 +4046,14 @@ module Impl<FullStateConfigSig Config> {
notExpectsContent(node) or
expectsContentEx(node, ap.getHead())
) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), t)
else any()
strengthenType(node, t0, t)
}
pragma[nomagic]
private predicate partialPathTypeStrengthen(
DataFlowType t0, PartialAccessPath ap, DataFlowType t
) {
partialPathStep1(_, _, _, _, _, _, _, _, t0, t, ap) and t0 != t
}
/**
@@ -4183,7 +4232,8 @@ module Impl<FullStateConfigSig Config> {
}
}
private predicate partialPathStep(
pragma[nomagic]
private predicate partialPathStep0(
PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap
) {
@@ -4309,6 +4359,11 @@ module Impl<FullStateConfigSig Config> {
DataFlowType t1, PartialAccessPath ap1, Content c, DataFlowType t2, PartialAccessPath ap2
) {
partialPathStoreStep(_, t1, ap1, c, _, t2, ap2)
or
exists(DataFlowType t0 |
partialPathTypeStrengthen(t0, ap2, t2) and
apConsFwd(t1, ap1, c, t0, ap2)
)
}
pragma[nomagic]

View File

@@ -54,12 +54,7 @@ private module Cached {
fa.getField() instanceof InstanceField and ia.isImplicitFieldQualifier(fa)
)
} or
TSummaryInternalNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
FlowSummaryImpl::Private::summaryNodeRange(c, state)
} or
TSummaryParameterNode(SummarizedCallable c, int pos) {
FlowSummaryImpl::Private::summaryParameterNodeRange(c, pos)
} or
TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) or
TFieldValueNode(Field f)
cached
@@ -132,8 +127,6 @@ module Public {
or
result = this.(ImplicitPostUpdateNode).getPreUpdateNode().getType()
or
result = this.(SummaryParameterNode).getTypeImpl()
or
result = this.(FieldValueNode).getField().getType()
}
@@ -378,8 +371,7 @@ module Private {
result.asCallable() = n.(ImplicitInstanceAccess).getInstanceAccess().getEnclosingCallable() or
result.asCallable() = n.(MallocNode).getClassInstanceExpr().getEnclosingCallable() or
result = nodeGetEnclosingCallable(n.(ImplicitPostUpdateNode).getPreUpdateNode()) or
n = TSummaryInternalNode(result.asSummarizedCallable(), _) or
n = TSummaryParameterNode(result.asSummarizedCallable(), _) or
result.asSummarizedCallable() = n.(FlowSummaryNode).getSummarizedCallable() or
result.asFieldScope() = n.(FieldValueNode).getField()
}
@@ -407,7 +399,7 @@ module Private {
or
this = getInstanceArgument(_)
or
this.(SummaryNode).isArgumentOf(_, _)
this.(FlowSummaryNode).isArgumentOf(_, _)
}
/**
@@ -424,7 +416,7 @@ module Private {
or
pos = -1 and this = getInstanceArgument(call.asCall())
or
this.(SummaryNode).isArgumentOf(call, pos)
this.(FlowSummaryNode).isArgumentOf(call, pos)
}
/** Gets the call in which this node is an argument. */
@@ -435,7 +427,7 @@ module Private {
class ReturnNode extends Node {
ReturnNode() {
exists(ReturnStmt ret | this.asExpr() = ret.getResult()) or
this.(SummaryNode).isReturn()
this.(FlowSummaryNode).isReturn()
}
/** Gets the kind of this returned value. */
@@ -447,61 +439,57 @@ module Private {
OutNode() {
this.asExpr() instanceof MethodAccess
or
this.(SummaryNode).isOut(_)
this.(FlowSummaryNode).isOut(_)
}
/** Gets the underlying call. */
DataFlowCall getCall() {
result.asCall() = this.asExpr()
or
this.(SummaryNode).isOut(result)
this.(FlowSummaryNode).isOut(result)
}
}
/**
* A data-flow node used to model flow summaries.
*/
class SummaryNode extends Node, TSummaryInternalNode {
private SummarizedCallable c;
private FlowSummaryImpl::Private::SummaryNodeState state;
class FlowSummaryNode extends Node, TFlowSummaryNode {
FlowSummaryImpl::Private::SummaryNode getSummaryNode() { this = TFlowSummaryNode(result) }
SummaryNode() { this = TSummaryInternalNode(c, state) }
SummarizedCallable getSummarizedCallable() {
result = this.getSummaryNode().getSummarizedCallable()
}
override Location getLocation() { result = c.getLocation() }
override Location getLocation() { result = this.getSummarizedCallable().getLocation() }
override string toString() { result = "[summary] " + state + " in " + c }
override string toString() { result = this.getSummaryNode().toString() }
/** Holds if this summary node is the `i`th argument of `call`. */
predicate isArgumentOf(DataFlowCall call, int i) {
FlowSummaryImpl::Private::summaryArgumentNode(call, this, i)
FlowSummaryImpl::Private::summaryArgumentNode(call, this.getSummaryNode(), i)
}
/** Holds if this summary node is a return node. */
predicate isReturn() { FlowSummaryImpl::Private::summaryReturnNode(this, _) }
predicate isReturn() { FlowSummaryImpl::Private::summaryReturnNode(this.getSummaryNode(), _) }
/** Holds if this summary node is an out node for `call`. */
predicate isOut(DataFlowCall call) { FlowSummaryImpl::Private::summaryOutNode(call, this, _) }
predicate isOut(DataFlowCall call) {
FlowSummaryImpl::Private::summaryOutNode(call, this.getSummaryNode(), _)
}
}
SummaryNode getSummaryNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
result = TSummaryInternalNode(c, state)
}
class SummaryParameterNode extends ParameterNode, TSummaryParameterNode {
private SummarizedCallable sc;
private int pos_;
SummaryParameterNode() { this = TSummaryParameterNode(sc, pos_) }
override Location getLocation() { result = sc.getLocation() }
override string toString() { result = "[summary param] " + pos_ + " in " + sc }
override predicate isParameterOf(DataFlowCallable c, int pos) {
c.asSummarizedCallable() = sc and pos = pos_
class SummaryParameterNode extends ParameterNode, FlowSummaryNode {
SummaryParameterNode() {
FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), _)
}
Type getTypeImpl() { result = sc.getParameterType(pos_) }
private int getPosition() {
FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), result)
}
override predicate isParameterOf(DataFlowCallable c, int pos) {
c.asSummarizedCallable() = this.getSummarizedCallable() and pos = this.getPosition()
}
}
}
@@ -523,10 +511,12 @@ private class MallocNode extends Node, TMallocNode {
ClassInstanceExpr getClassInstanceExpr() { result = cie }
}
private class SummaryPostUpdateNode extends SummaryNode, PostUpdateNode {
private Node pre;
private class SummaryPostUpdateNode extends FlowSummaryNode, PostUpdateNode {
private FlowSummaryNode pre;
SummaryPostUpdateNode() { FlowSummaryImpl::Private::summaryPostUpdateNode(this, pre) }
SummaryPostUpdateNode() {
FlowSummaryImpl::Private::summaryPostUpdateNode(this.getSummaryNode(), pre.getSummaryNode())
}
override Node getPreUpdateNode() { result = pre }
}

View File

@@ -85,7 +85,8 @@ predicate jumpStep(Node node1, Node node2) {
any(AdditionalValueStep a).step(node1, node2) and
node1.getEnclosingCallable() != node2.getEnclosingCallable()
or
FlowSummaryImpl::Private::Steps::summaryJumpStep(node1, node2)
FlowSummaryImpl::Private::Steps::summaryJumpStep(node1.(FlowSummaryNode).getSummaryNode(),
node2.(FlowSummaryNode).getSummaryNode())
}
/**
@@ -114,7 +115,8 @@ predicate storeStep(Node node1, Content f, Node node2) {
or
f instanceof ArrayContent and arrayStoreStep(node1, node2)
or
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1, f, node2)
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), f,
node2.(FlowSummaryNode).getSummaryNode())
}
/**
@@ -145,7 +147,8 @@ predicate readStep(Node node1, Content f, Node node2) {
or
f instanceof CollectionContent and collectionReadStep(node1, node2)
or
FlowSummaryImpl::Private::Steps::summaryReadStep(node1, f, node2)
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), f,
node2.(FlowSummaryNode).getSummaryNode())
}
/**
@@ -160,7 +163,7 @@ predicate clearsContent(Node n, Content c) {
c.(FieldContent).getField() = fa.getField()
)
or
FlowSummaryImpl::Private::Steps::summaryClearsContent(n, c)
FlowSummaryImpl::Private::Steps::summaryClearsContent(n.(FlowSummaryNode).getSummaryNode(), c)
}
/**
@@ -168,7 +171,7 @@ predicate clearsContent(Node n, Content c) {
* at node `n`.
*/
predicate expectsContent(Node n, ContentSet c) {
FlowSummaryImpl::Private::Steps::summaryExpectsContent(n, c)
FlowSummaryImpl::Private::Steps::summaryExpectsContent(n.(FlowSummaryNode).getSummaryNode(), c)
}
/**
@@ -176,7 +179,7 @@ predicate expectsContent(Node n, ContentSet c) {
* possible flow. A single type is used for all numeric types to account for
* numeric conversions, and otherwise the erasure is used.
*/
DataFlowType getErasedRepr(Type t) {
RefType getErasedRepr(Type t) {
exists(Type e | e = t.getErasure() |
if e instanceof NumericOrCharType
then result.(BoxedType).getPrimitiveType().getName() = "double"
@@ -189,11 +192,18 @@ DataFlowType getErasedRepr(Type t) {
t instanceof NullType and result instanceof TypeObject
}
class DataFlowType extends SrcRefType {
DataFlowType() { this = getErasedRepr(_) }
}
pragma[nomagic]
predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { t1.getASourceSupertype+() = t2 }
pragma[noinline]
DataFlowType getNodeType(Node n) {
result = getErasedRepr(n.getTypeBound())
or
result = FlowSummaryImpl::Private::summaryNodeType(n)
result = FlowSummaryImpl::Private::summaryNodeType(n.(FlowSummaryNode).getSummaryNode())
}
/** Gets a string representation of a type returned by `getErasedRepr`. */
@@ -232,6 +242,12 @@ class CastNode extends ExprNode {
CastNode() { this.getExpr() instanceof CastingExpr }
}
/**
* Holds if `n` should never be skipped over in the `PathGraph` and in path
* explanations.
*/
predicate neverSkipInPathGraph(Node n) { none() }
private newtype TDataFlowCallable =
TSrcCallable(Callable c) or
TSummarizedCallable(SummarizedCallable c) or
@@ -259,11 +275,9 @@ class DataFlowCallable extends TDataFlowCallable {
class DataFlowExpr = Expr;
class DataFlowType = RefType;
private newtype TDataFlowCall =
TCall(Call c) or
TSummaryCall(SummarizedCallable c, Node receiver) {
TSummaryCall(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver) {
FlowSummaryImpl::Private::summaryCallbackRange(c, receiver)
}
@@ -313,12 +327,12 @@ class SrcCall extends DataFlowCall, TCall {
/** A synthesized call inside a `SummarizedCallable`. */
class SummaryCall extends DataFlowCall, TSummaryCall {
private SummarizedCallable c;
private Node receiver;
private FlowSummaryImpl::Private::SummaryNode receiver;
SummaryCall() { this = TSummaryCall(c, receiver) }
/** Gets the data flow node that this call targets. */
Node getReceiver() { result = receiver }
FlowSummaryImpl::Private::SummaryNode getReceiver() { result = receiver }
override DataFlowCallable getEnclosingCallable() { result.asSummarizedCallable() = c }
@@ -378,10 +392,7 @@ predicate forceHighPrecision(Content c) {
}
/** Holds if `n` should be hidden from path explanations. */
predicate nodeIsHidden(Node n) {
n instanceof SummaryNode or
n instanceof SummaryParameterNode
}
predicate nodeIsHidden(Node n) { n instanceof FlowSummaryNode }
class LambdaCallKind = Method; // the "apply" method in the functional interface
@@ -399,7 +410,7 @@ predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c)
/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
receiver = call.(SummaryCall).getReceiver() and
receiver.(FlowSummaryNode).getSummaryNode() = call.(SummaryCall).getReceiver() and
getNodeDataFlowType(receiver)
.getSourceDeclaration()
.(FunctionalInterface)

View File

@@ -183,7 +183,8 @@ private predicate simpleLocalFlowStep0(Node node1, Node node2) {
node1.(ArgumentNode).argumentOf(any(DataFlowCall c | c.asCall() = ma), argNo)
)
or
FlowSummaryImpl::Private::Steps::summaryLocalStep(node1, node2, true)
FlowSummaryImpl::Private::Steps::summaryLocalStep(node1.(FlowSummaryNode).getSummaryNode(),
node2.(FlowSummaryNode).getSummaryNode(), true)
}
/**

View File

@@ -180,6 +180,11 @@ module Public {
result = "Argument[" + getParameterPosition(pos) + "]"
)
or
exists(string synthetic |
sc = TSyntheticGlobalSummaryComponent(synthetic) and
result = "SyntheticGlobal[" + synthetic + "]"
)
or
sc = TReturnSummaryComponent(getReturnValueKind()) and result = "ReturnValue"
}
@@ -505,6 +510,9 @@ module Private {
or
// Add the post-update node corresponding to the requested argument node
outputState(c, s) and isCallbackParameter(s)
or
// Add the parameter node for parameter side-effects
outputState(c, s) and s = SummaryComponentStack::argument(_)
}
private newtype TSummaryNodeState =
@@ -530,7 +538,7 @@ module Private {
* this state represents that the components in `s` _remain to be written_ to
* the output.
*/
class SummaryNodeState extends TSummaryNodeState {
private class SummaryNodeState extends TSummaryNodeState {
/** Holds if this state is a valid input state for `c`. */
pragma[nomagic]
predicate isInputState(SummarizedCallable c, SummaryComponentStack s) {
@@ -559,6 +567,42 @@ module Private {
}
}
private newtype TSummaryNode =
TSummaryInternalNode(SummarizedCallable c, SummaryNodeState state) {
summaryNodeRange(c, state)
} or
TSummaryParameterNode(SummarizedCallable c, ParameterPosition pos) {
summaryParameterNodeRange(c, pos)
}
abstract class SummaryNode extends TSummaryNode {
abstract string toString();
abstract SummarizedCallable getSummarizedCallable();
}
private class SummaryInternalNode extends SummaryNode, TSummaryInternalNode {
private SummarizedCallable c;
private SummaryNodeState state;
SummaryInternalNode() { this = TSummaryInternalNode(c, state) }
override string toString() { result = "[summary] " + state + " in " + c }
override SummarizedCallable getSummarizedCallable() { result = c }
}
private class SummaryParamNode extends SummaryNode, TSummaryParameterNode {
private SummarizedCallable c;
private ParameterPosition pos;
SummaryParamNode() { this = TSummaryParameterNode(c, pos) }
override string toString() { result = "[summary param] " + pos + " in " + c }
override SummarizedCallable getSummarizedCallable() { result = c }
}
/**
* Holds if `state` represents having read from a parameter at position
* `pos` in `c`. In this case we are not synthesizing a data-flow node,
@@ -574,7 +618,7 @@ module Private {
* Holds if a synthesized summary node is needed for the state `state` in summarized
* callable `c`.
*/
predicate summaryNodeRange(SummarizedCallable c, SummaryNodeState state) {
private predicate summaryNodeRange(SummarizedCallable c, SummaryNodeState state) {
state.isInputState(c, _) and
not parameterReadState(c, state, _)
or
@@ -582,22 +626,22 @@ module Private {
}
pragma[noinline]
private Node summaryNodeInputState(SummarizedCallable c, SummaryComponentStack s) {
private SummaryNode summaryNodeInputState(SummarizedCallable c, SummaryComponentStack s) {
exists(SummaryNodeState state | state.isInputState(c, s) |
result = summaryNode(c, state)
result = TSummaryInternalNode(c, state)
or
exists(ParameterPosition pos |
parameterReadState(c, state, pos) and
result.(ParamNode).isParameterOf(inject(c), pos)
result = TSummaryParameterNode(c, pos)
)
)
}
pragma[noinline]
private Node summaryNodeOutputState(SummarizedCallable c, SummaryComponentStack s) {
private SummaryNode summaryNodeOutputState(SummarizedCallable c, SummaryComponentStack s) {
exists(SummaryNodeState state |
state.isOutputState(c, s) and
result = summaryNode(c, state)
result = TSummaryInternalNode(c, state)
)
}
@@ -605,12 +649,14 @@ module Private {
* Holds if a write targets `post`, which is a post-update node for a
* parameter at position `pos` in `c`.
*/
private predicate isParameterPostUpdate(Node post, SummarizedCallable c, ParameterPosition pos) {
private predicate isParameterPostUpdate(
SummaryNode post, SummarizedCallable c, ParameterPosition pos
) {
post = summaryNodeOutputState(c, SummaryComponentStack::argument(pos))
}
/** Holds if a parameter node at position `pos` is required for `c`. */
predicate summaryParameterNodeRange(SummarizedCallable c, ParameterPosition pos) {
private predicate summaryParameterNodeRange(SummarizedCallable c, ParameterPosition pos) {
parameterReadState(c, _, pos)
or
// Same as `isParameterPostUpdate(_, c, pos)`, but can be used in a negative context
@@ -618,7 +664,7 @@ module Private {
}
private predicate callbackOutput(
SummarizedCallable c, SummaryComponentStack s, Node receiver, ReturnKind rk
SummarizedCallable c, SummaryComponentStack s, SummaryNode receiver, ReturnKind rk
) {
any(SummaryNodeState state).isInputState(c, s) and
s.head() = TReturnSummaryComponent(rk) and
@@ -626,7 +672,7 @@ module Private {
}
private predicate callbackInput(
SummarizedCallable c, SummaryComponentStack s, Node receiver, ArgumentPosition pos
SummarizedCallable c, SummaryComponentStack s, SummaryNode receiver, ArgumentPosition pos
) {
any(SummaryNodeState state).isOutputState(c, s) and
s.head() = TParameterSummaryComponent(pos) and
@@ -634,7 +680,7 @@ module Private {
}
/** Holds if a call targeting `receiver` should be synthesized inside `c`. */
predicate summaryCallbackRange(SummarizedCallable c, Node receiver) {
predicate summaryCallbackRange(SummarizedCallable c, SummaryNode receiver) {
callbackOutput(c, _, receiver, _)
or
callbackInput(c, _, receiver, _)
@@ -647,10 +693,10 @@ module Private {
* `getContentType()`, `getReturnType()`, `getCallbackParameterType()`, and
* `getCallbackReturnType()`.
*/
DataFlowType summaryNodeType(Node n) {
exists(Node pre |
DataFlowType summaryNodeType(SummaryNode n) {
exists(SummaryNode pre |
summaryPostUpdateNode(n, pre) and
result = getNodeType(pre)
result = summaryNodeType(pre)
)
or
exists(SummarizedCallable c, SummaryComponentStack s, SummaryComponent head | head = s.head() |
@@ -662,12 +708,12 @@ module Private {
)
or
head = TWithoutContentSummaryComponent(_) and
result = getNodeType(summaryNodeInputState(c, s.tail()))
result = summaryNodeType(summaryNodeInputState(c, s.tail()))
or
exists(ReturnKind rk |
head = TReturnSummaryComponent(rk) and
result =
getCallbackReturnType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
getCallbackReturnType(summaryNodeType(summaryNodeInputState(pragma[only_bind_out](c),
s.tail())), rk)
)
or
@@ -675,6 +721,11 @@ module Private {
head = TSyntheticGlobalSummaryComponent(sg) and
result = getSyntheticGlobalType(sg)
)
or
exists(ParameterPosition pos |
head = TArgumentSummaryComponent(pos) and
result = getParameterType(c, pos)
)
)
or
n = summaryNodeOutputState(c, s) and
@@ -691,7 +742,7 @@ module Private {
or
exists(ArgumentPosition pos | head = TParameterSummaryComponent(pos) |
result =
getCallbackParameterType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
getCallbackParameterType(summaryNodeType(summaryNodeInputState(pragma[only_bind_out](c),
s.tail())), pos)
)
or
@@ -703,9 +754,14 @@ module Private {
)
}
/** Holds if summary node `p` is a parameter with position `pos`. */
predicate summaryParameterNode(SummaryNode p, ParameterPosition pos) {
p = TSummaryParameterNode(_, pos)
}
/** Holds if summary node `out` contains output of kind `rk` from call `c`. */
predicate summaryOutNode(DataFlowCall c, Node out, ReturnKind rk) {
exists(SummarizedCallable callable, SummaryComponentStack s, Node receiver |
predicate summaryOutNode(DataFlowCall c, SummaryNode out, ReturnKind rk) {
exists(SummarizedCallable callable, SummaryComponentStack s, SummaryNode receiver |
callbackOutput(callable, s, receiver, rk) and
out = summaryNodeInputState(callable, s) and
c = summaryDataFlowCall(receiver)
@@ -713,8 +769,8 @@ module Private {
}
/** Holds if summary node `arg` is at position `pos` in the call `c`. */
predicate summaryArgumentNode(DataFlowCall c, Node arg, ArgumentPosition pos) {
exists(SummarizedCallable callable, SummaryComponentStack s, Node receiver |
predicate summaryArgumentNode(DataFlowCall c, SummaryNode arg, ArgumentPosition pos) {
exists(SummarizedCallable callable, SummaryComponentStack s, SummaryNode receiver |
callbackInput(callable, s, receiver, pos) and
arg = summaryNodeOutputState(callable, s) and
c = summaryDataFlowCall(receiver)
@@ -722,10 +778,10 @@ module Private {
}
/** Holds if summary node `post` is a post-update node with pre-update node `pre`. */
predicate summaryPostUpdateNode(Node post, Node pre) {
predicate summaryPostUpdateNode(SummaryNode post, SummaryNode pre) {
exists(SummarizedCallable c, ParameterPosition pos |
isParameterPostUpdate(post, c, pos) and
pre.(ParamNode).isParameterOf(inject(c), pos)
pre = TSummaryParameterNode(c, pos)
)
or
exists(SummarizedCallable callable, SummaryComponentStack s |
@@ -736,7 +792,7 @@ module Private {
}
/** Holds if summary node `ret` is a return node of kind `rk`. */
predicate summaryReturnNode(Node ret, ReturnKind rk) {
predicate summaryReturnNode(SummaryNode ret, ReturnKind rk) {
exists(SummaryComponentStack s |
ret = summaryNodeOutputState(_, s) and
s = TSingletonSummaryComponentStack(TReturnSummaryComponent(rk))
@@ -748,7 +804,9 @@ module Private {
* node, and back out to `p`.
*/
predicate summaryAllowParameterReturnInSelf(ParamNode p) {
exists(SummarizedCallable c, ParameterPosition ppos | p.isParameterOf(inject(c), ppos) |
exists(SummarizedCallable c, ParameterPosition ppos |
p.isParameterOf(inject(c), pragma[only_bind_into](ppos))
|
exists(SummaryComponentStack inputContents, SummaryComponentStack outputContents |
summary(c, inputContents, outputContents, _) and
inputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(ppos)) and
@@ -763,7 +821,7 @@ module Private {
* Holds if there is a local step from `pred` to `succ`, which is synthesized
* from a flow summary.
*/
predicate summaryLocalStep(Node pred, Node succ, boolean preservesValue) {
predicate summaryLocalStep(SummaryNode pred, SummaryNode succ, boolean preservesValue) {
exists(
SummarizedCallable c, SummaryComponentStack inputContents,
SummaryComponentStack outputContents
@@ -789,7 +847,7 @@ module Private {
* Holds if there is a read step of content `c` from `pred` to `succ`, which
* is synthesized from a flow summary.
*/
predicate summaryReadStep(Node pred, ContentSet c, Node succ) {
predicate summaryReadStep(SummaryNode pred, ContentSet c, SummaryNode succ) {
exists(SummarizedCallable sc, SummaryComponentStack s |
pred = summaryNodeInputState(sc, s.tail()) and
succ = summaryNodeInputState(sc, s) and
@@ -801,7 +859,7 @@ module Private {
* Holds if there is a store step of content `c` from `pred` to `succ`, which
* is synthesized from a flow summary.
*/
predicate summaryStoreStep(Node pred, ContentSet c, Node succ) {
predicate summaryStoreStep(SummaryNode pred, ContentSet c, SummaryNode succ) {
exists(SummarizedCallable sc, SummaryComponentStack s |
pred = summaryNodeOutputState(sc, s) and
succ = summaryNodeOutputState(sc, s.tail()) and
@@ -813,7 +871,7 @@ module Private {
* Holds if there is a jump step from `pred` to `succ`, which is synthesized
* from a flow summary.
*/
predicate summaryJumpStep(Node pred, Node succ) {
predicate summaryJumpStep(SummaryNode pred, SummaryNode succ) {
exists(SummaryComponentStack s |
s = SummaryComponentStack::singleton(SummaryComponent::syntheticGlobal(_)) and
pred = summaryNodeOutputState(_, s) and
@@ -840,9 +898,9 @@ module Private {
* `a` on line 2 to the post-update node for `a` on that line (via an intermediate
* node where field `b` is cleared).
*/
predicate summaryClearsContent(Node n, ContentSet c) {
predicate summaryClearsContent(SummaryNode n, ContentSet c) {
exists(SummarizedCallable sc, SummaryNodeState state, SummaryComponentStack stack |
n = summaryNode(sc, state) and
n = TSummaryInternalNode(sc, state) and
state.isInputState(sc, stack) and
stack.head() = SummaryComponent::withoutContent(c)
)
@@ -852,9 +910,9 @@ module Private {
* Holds if the value that is being tracked is expected to be stored inside
* content `c` at `n`.
*/
predicate summaryExpectsContent(Node n, ContentSet c) {
predicate summaryExpectsContent(SummaryNode n, ContentSet c) {
exists(SummarizedCallable sc, SummaryNodeState state, SummaryComponentStack stack |
n = summaryNode(sc, state) and
n = TSummaryInternalNode(sc, state) and
state.isInputState(sc, stack) and
stack.head() = SummaryComponent::withContent(c)
)
@@ -862,17 +920,17 @@ module Private {
pragma[noinline]
private predicate viableParam(
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, ParamNode p
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, SummaryParamNode p
) {
exists(DataFlowCallable c |
c = inject(sc) and
p.isParameterOf(c, ppos) and
p = TSummaryParameterNode(sc, ppos) and
c = viableCallable(call)
)
}
pragma[nomagic]
private ParamNode summaryArgParam0(DataFlowCall call, ArgNode arg, SummarizedCallable sc) {
private SummaryParamNode summaryArgParam(DataFlowCall call, ArgNode arg, SummarizedCallable sc) {
exists(ParameterPosition ppos |
argumentPositionMatch(call, arg, ppos) and
viableParam(call, sc, ppos, result)
@@ -884,12 +942,12 @@ module Private {
* local steps. `clearsOrExpects` records whether any node on the path from `p` to
* `n` either clears or expects contents.
*/
private predicate paramReachesLocal(ParamNode p, Node n, boolean clearsOrExpects) {
private predicate paramReachesLocal(SummaryParamNode p, SummaryNode n, boolean clearsOrExpects) {
viableParam(_, _, _, p) and
n = p and
clearsOrExpects = false
or
exists(Node mid, boolean clearsOrExpectsMid |
exists(SummaryNode mid, boolean clearsOrExpectsMid |
paramReachesLocal(p, mid, clearsOrExpectsMid) and
summaryLocalStep(mid, n, true) and
if
@@ -909,21 +967,33 @@ module Private {
*/
pragma[nomagic]
predicate prohibitsUseUseFlow(ArgNode arg, SummarizedCallable sc) {
exists(ParamNode p, ParameterPosition ppos, Node ret |
exists(SummaryParamNode p, ParameterPosition ppos, SummaryNode ret |
paramReachesLocal(p, ret, true) and
p = summaryArgParam0(_, arg, sc) and
p.isParameterOf(_, pragma[only_bind_into](ppos)) and
p = summaryArgParam(_, arg, sc) and
p = TSummaryParameterNode(_, pragma[only_bind_into](ppos)) and
isParameterPostUpdate(ret, _, pragma[only_bind_into](ppos))
)
}
pragma[nomagic]
private predicate summaryReturnNodeExt(SummaryNode ret, ReturnKindExt rk) {
summaryReturnNode(ret, rk.(ValueReturnKind).getKind())
or
exists(SummaryParamNode p, SummaryNode pre, ParameterPosition pos |
paramReachesLocal(p, pre, _) and
summaryPostUpdateNode(ret, pre) and
p = TSummaryParameterNode(_, pos) and
rk.(ParamUpdateReturnKind).getPosition() = pos
)
}
bindingset[ret]
private ParamNode summaryArgParam(
ArgNode arg, ReturnNodeExt ret, OutNodeExt out, SummarizedCallable sc
private SummaryParamNode summaryArgParamRetOut(
ArgNode arg, SummaryNode ret, OutNodeExt out, SummarizedCallable sc
) {
exists(DataFlowCall call, ReturnKindExt rk |
result = summaryArgParam0(call, arg, sc) and
ret.getKind() = pragma[only_bind_into](rk) and
result = summaryArgParam(call, arg, sc) and
summaryReturnNodeExt(ret, pragma[only_bind_into](rk)) and
out = pragma[only_bind_into](rk).getAnOutNode(call)
)
}
@@ -936,9 +1006,9 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryThroughStepValue(ArgNode arg, Node out, SummarizedCallable sc) {
exists(ReturnKind rk, ReturnNode ret, DataFlowCall call |
summaryLocalStep(summaryArgParam0(call, arg, sc), ret, true) and
ret.getKind() = pragma[only_bind_into](rk) and
exists(ReturnKind rk, SummaryNode ret, DataFlowCall call |
summaryLocalStep(summaryArgParam(call, arg, sc), ret, true) and
summaryReturnNode(ret, pragma[only_bind_into](rk)) and
out = getAnOutNode(call, pragma[only_bind_into](rk))
)
}
@@ -951,7 +1021,9 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryThroughStepTaint(ArgNode arg, Node out, SummarizedCallable sc) {
exists(ReturnNodeExt ret | summaryLocalStep(summaryArgParam(arg, ret, out, sc), ret, false))
exists(SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), ret, false)
)
}
/**
@@ -962,8 +1034,8 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryGetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
exists(Node mid, ReturnNodeExt ret |
summaryReadStep(summaryArgParam(arg, ret, out, sc), c, mid) and
exists(SummaryNode mid, SummaryNode ret |
summaryReadStep(summaryArgParamRetOut(arg, ret, out, sc), c, mid) and
summaryLocalStep(mid, ret, _)
)
}
@@ -976,8 +1048,8 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summarySetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
exists(Node mid, ReturnNodeExt ret |
summaryLocalStep(summaryArgParam(arg, ret, out, sc), mid, _) and
exists(SummaryNode mid, SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), mid, _) and
summaryStoreStep(mid, c, ret)
)
}
@@ -1344,11 +1416,11 @@ module Private {
}
private newtype TNodeOrCall =
MkNode(Node n) {
MkNode(SummaryNode n) {
exists(RelevantSummarizedCallable c |
n = summaryNode(c, _)
n = TSummaryInternalNode(c, _)
or
n.(ParamNode).isParameterOf(inject(c), _)
n = TSummaryParameterNode(c, _)
)
} or
MkCall(DataFlowCall call) {
@@ -1357,7 +1429,7 @@ module Private {
}
private class NodeOrCall extends TNodeOrCall {
Node asNode() { this = MkNode(result) }
SummaryNode asNode() { this = MkNode(result) }
DataFlowCall asCall() { this = MkCall(result) }
@@ -1377,9 +1449,11 @@ module Private {
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.asNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
or
this.asCall().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
filepath = "" and
startline = 0 and
startcolumn = 0 and
endline = 0 and
endcolumn = 0
}
}

View File

@@ -26,15 +26,17 @@ DataFlowCallable inject(SummarizedCallable c) { result.asSummarizedCallable() =
/** Gets the parameter position of the instance parameter. */
ArgumentPosition callbackSelfParameterPosition() { result = -1 }
/** Gets the synthesized summary data-flow node for the given values. */
Node summaryNode(SummarizedCallable c, SummaryNodeState state) { result = getSummaryNode(c, state) }
/** Gets the synthesized data-flow call for `receiver`. */
SummaryCall summaryDataFlowCall(Node receiver) { result.getReceiver() = receiver }
SummaryCall summaryDataFlowCall(SummaryNode receiver) { result.getReceiver() = receiver }
/** Gets the type of content `c`. */
DataFlowType getContentType(Content c) { result = c.getType() }
/** Gets the type of the parameter at the given position. */
DataFlowType getParameterType(SummarizedCallable c, ParameterPosition pos) {
result = getErasedRepr(c.getParameterType(pos))
}
/** Gets the return type of kind `rk` for callable `c`. */
DataFlowType getReturnType(SummarizedCallable c, ReturnKind rk) {
result = getErasedRepr(c.getReturnType()) and

View File

@@ -86,6 +86,7 @@ module LocalTaintFlow<nodeSig/1 source, nodeSig/1 sink> {
cached
private module Cached {
private import DataFlowImplCommon as DataFlowImplCommon
private import DataFlowPrivate as DataFlowPrivate
cached
predicate forceCachingInSameStage() { DataFlowImplCommon::forceCachingInSameStage() }
@@ -136,7 +137,8 @@ private module Cached {
)
)
or
FlowSummaryImpl::Private::Steps::summaryLocalStep(src, sink, false)
FlowSummaryImpl::Private::Steps::summaryLocalStep(src.(DataFlowPrivate::FlowSummaryNode)
.getSummaryNode(), sink.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false)
}
/**

View File

@@ -456,9 +456,6 @@ class ArbitraryXmlEntryPoint extends ReflectivelyConstructedClass {
}
}
/** DEPRECATED: Alias for ArbitraryXmlEntryPoint */
deprecated class ArbitraryXMLEntryPoint = ArbitraryXmlEntryPoint;
/** A Selenium PageObject, created by a call to PageFactory.initElements(..). */
class SeleniumPageObjectEntryPoint extends ReflectivelyConstructedClass instanceof SeleniumPageObject
{ }

View File

@@ -38,9 +38,6 @@ class UrlConnectionGetInputStreamMethod extends Method {
}
}
/** DEPRECATED: Alias for UrlConnectionGetInputStreamMethod */
deprecated class URLConnectionGetInputStreamMethod = UrlConnectionGetInputStreamMethod;
/** The method `java.net.Socket::getInputStream`. */
class SocketGetInputStreamMethod extends Method {
SocketGetInputStreamMethod() {

View File

@@ -128,9 +128,6 @@ class HttpServletRequestGetRequestUrlMethod extends Method {
}
}
/** DEPRECATED: Alias for HttpServletRequestGetRequestUrlMethod */
deprecated class HttpServletRequestGetRequestURLMethod = HttpServletRequestGetRequestUrlMethod;
/**
* The method `getRequestURI()` declared in `javax.servlet.http.HttpServletRequest`.
*/
@@ -339,9 +336,6 @@ class ServletWebXmlListenerType extends RefType {
}
}
/** DEPRECATED: Alias for ServletWebXmlListenerType */
deprecated class ServletWebXMLListenerType = ServletWebXmlListenerType;
/** Holds if `m` is a request handler method (for example `doGet` or `doPost`). */
predicate isServletRequestMethod(Method m) {
m.getDeclaringType() instanceof ServletClass and

View File

@@ -29,9 +29,6 @@ class TypeUnboundIdLdapConnection extends Class {
}
}
/** DEPRECATED: Alias for TypeUnboundIdLdapConnection */
deprecated class TypeUnboundIdLDAPConnection = TypeUnboundIdLdapConnection;
/*--- Methods ---*/
/** A method with the name `setBaseDN` declared in `com.unboundid.ldap.sdk.SearchRequest`. */
class MethodUnboundIdSearchRequestSetBaseDN extends Method {
@@ -103,9 +100,6 @@ class MethodUnboundIdLdapConnectionSearch extends Method {
}
}
/** DEPRECATED: Alias for MethodUnboundIdLdapConnectionSearch */
deprecated class MethodUnboundIdLDAPConnectionSearch = MethodUnboundIdLdapConnectionSearch;
/** A method with the name `asyncSearch` declared in `com.unboundid.ldap.sdk.LDAPConnection`. */
class MethodUnboundIdLdapConnectionAsyncSearch extends Method {
MethodUnboundIdLdapConnectionAsyncSearch() {
@@ -114,10 +108,6 @@ class MethodUnboundIdLdapConnectionAsyncSearch extends Method {
}
}
/** DEPRECATED: Alias for MethodUnboundIdLdapConnectionAsyncSearch */
deprecated class MethodUnboundIdLDAPConnectionAsyncSearch =
MethodUnboundIdLdapConnectionAsyncSearch;
/** A method with the name `searchForEntry` declared in `com.unboundid.ldap.sdk.LDAPConnection`. */
class MethodUnboundIdLdapConnectionSearchForEntry extends Method {
MethodUnboundIdLdapConnectionSearchForEntry() {
@@ -125,7 +115,3 @@ class MethodUnboundIdLdapConnectionSearchForEntry extends Method {
this.hasName("searchForEntry")
}
}
/** DEPRECATED: Alias for MethodUnboundIdLdapConnectionSearchForEntry */
deprecated class MethodUnboundIdLDAPConnectionSearchForEntry =
MethodUnboundIdLdapConnectionSearchForEntry;

View File

@@ -4,12 +4,6 @@ import java
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.dataflow.FlowSources
private class DefaultAndroidWidgetSources extends RemoteFlowSource {
DefaultAndroidWidgetSources() { sourceNode(this, "android-widget") }
override string getSourceType() { result = "Android widget source" }
}
private class EditableToStringStep extends AdditionalTaintStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(MethodAccess ma |

View File

@@ -0,0 +1,38 @@
/** Provides classes and predicates related to the Hudson framework. */
import java
private import semmle.code.java.dataflow.FlowSources
private import semmle.code.java.frameworks.stapler.Stapler
private import semmle.code.java.security.XSS
/** A method declared in a subtype of `hudson.model.Descriptor` that returns an `HttpResponse`. */
class HudsonWebMethod extends Method {
HudsonWebMethod() {
this.getReturnType().(RefType).getASourceSupertype*() instanceof HttpResponse and
this.getDeclaringType().getASourceSupertype*().hasQualifiedName("hudson.model", "Descriptor")
}
}
private class FilePathRead extends LocalUserInput {
FilePathRead() {
this.asExpr()
.(MethodAccess)
.getMethod()
.hasQualifiedName("hudson", "FilePath",
[
"newInputStreamDenyingSymlinkAsNeeded", "openInputStream", "read", "readFromOffset",
"readToString"
])
}
}
private class HudsonUtilXssSanitizer extends XssSanitizer {
HudsonUtilXssSanitizer() {
this.asExpr()
.(MethodAccess)
.getMethod()
// Not including xmlEscape because it only accounts for >, <, and &.
// It does not account for ", or ', which makes it an incomplete XSS sanitizer.
.hasQualifiedName("hudson", "Util", "escape")
}
}

View File

@@ -20,9 +20,6 @@ class JacksonJsonIgnoreAnnotation extends NonReflectiveAnnotation {
}
}
/** DEPRECATED: Alias for JacksonJsonIgnoreAnnotation */
deprecated class JacksonJSONIgnoreAnnotation = JacksonJsonIgnoreAnnotation;
/** A type whose values may be serialized using the Jackson JSON framework. */
abstract class JacksonSerializableType extends Type { }

View File

@@ -26,9 +26,6 @@ class PersistenceXmlFile extends XmlFile {
}
}
/** DEPRECATED: Alias for PersistenceXmlFile */
deprecated class PersistenceXMLFile = PersistenceXmlFile;
/** The root `persistence` XML element in a `persistence.xml` file. */
class PersistenceXmlRoot extends XmlElement {
PersistenceXmlRoot() {

View File

@@ -35,9 +35,6 @@ class EjbJarXmlFile extends XmlFile {
}
}
/** DEPRECATED: Alias for EjbJarXmlFile */
deprecated class EjbJarXMLFile = EjbJarXmlFile;
/** The root `ejb-jar` XML element in an `ejb-jar.xml` file. */
class EjbJarRootElement extends XmlElement {
EjbJarRootElement() {

View File

@@ -16,9 +16,6 @@ class FacesConfigXmlFile extends XmlFile {
}
}
/** DEPRECATED: Alias for FacesConfigXmlFile */
deprecated class FacesConfigXMLFile = FacesConfigXmlFile;
/**
* An XML element in a `FacesConfigXMLFile`.
*/
@@ -31,9 +28,6 @@ class FacesConfigXmlElement extends XmlElement {
string getValue() { result = this.allCharactersString().trim() }
}
/** DEPRECATED: Alias for FacesConfigXmlElement */
deprecated class FacesConfigXMLElement = FacesConfigXmlElement;
/**
* An element in a JSF config file that declares a managed bean.
*/

View File

@@ -100,9 +100,6 @@ class SpringBeanXmlAutowiredSetterMethod extends Method {
}
}
/** DEPRECATED: Alias for SpringBeanXmlAutowiredSetterMethod */
deprecated class SpringBeanXMLAutowiredSetterMethod = SpringBeanXmlAutowiredSetterMethod;
/**
* A callable that is annotated with `@Autowired`.
*

View File

@@ -13,9 +13,6 @@ class SpringCamelXmlElement extends SpringXmlElement {
SpringCamelXmlElement() { this.getNamespace().getUri() = "http://camel.apache.org/schema/spring" }
}
/** DEPRECATED: Alias for SpringCamelXmlElement */
deprecated class SpringCamelXMLElement = SpringCamelXmlElement;
/**
* An element in a Spring beans file that defines an Apache Camel context.
*
@@ -25,9 +22,6 @@ class SpringCamelXmlContext extends SpringCamelXmlElement {
SpringCamelXmlContext() { this.getName() = "camelContext" }
}
/** DEPRECATED: Alias for SpringCamelXmlContext */
deprecated class SpringCamelXMLContext = SpringCamelXmlContext;
/**
* An element in a Spring beans file that defines an Apache Camel route context.
*
@@ -38,9 +32,6 @@ class SpringCamelXmlRouteContext extends SpringCamelXmlElement {
SpringCamelXmlRouteContext() { this.getName() = "routeContext" }
}
/** DEPRECATED: Alias for SpringCamelXmlRouteContext */
deprecated class SpringCamelXMLRouteContext = SpringCamelXmlRouteContext;
/**
* An element in a Spring beans files that defines an Apache Camel route.
*
@@ -58,9 +49,6 @@ class SpringCamelXmlRoute extends SpringCamelXmlElement {
}
}
/** DEPRECATED: Alias for SpringCamelXmlRoute */
deprecated class SpringCamelXMLRoute = SpringCamelXmlRoute;
/**
* An element in a Spring bean file that is logically contained in an Apache Camel route.
*/
@@ -71,9 +59,6 @@ class SpringCamelXmlRouteElement extends SpringCamelXmlElement {
}
}
/** DEPRECATED: Alias for SpringCamelXmlRouteElement */
deprecated class SpringCamelXMLRouteElement = SpringCamelXmlRouteElement;
/**
* A reference to a Spring bean in an Apache Camel route defined in a Spring beans file.
*
@@ -98,9 +83,6 @@ class SpringCamelXmlBeanRef extends SpringCamelXmlRouteElement {
RefType getBeanType() { result.getQualifiedName() = this.getAttribute("beanType").getValue() }
}
/** DEPRECATED: Alias for SpringCamelXmlBeanRef */
deprecated class SpringCamelXMLBeanRef = SpringCamelXmlBeanRef;
/**
* A declaration of a target in an Apache Camel route defined in a Spring beans file.
*
@@ -120,9 +102,6 @@ class SpringCamelXmlToElement extends SpringCamelXmlRouteElement {
deprecated string getURI() { result = this.getUri() }
}
/** DEPRECATED: Alias for SpringCamelXmlToElement */
deprecated class SpringCamelXMLToElement = SpringCamelXmlToElement;
/**
* A declaration of a Apache Camel "method" expression defined in a Spring beans file.
*
@@ -147,6 +126,3 @@ class SpringCamelXmlMethodElement extends SpringCamelXmlElement {
*/
RefType getBeanType() { result.getQualifiedName() = this.getAttribute("beanType").getValue() }
}
/** DEPRECATED: Alias for SpringCamelXmlMethodElement */
deprecated class SpringCamelXMLMethodElement = SpringCamelXmlMethodElement;

View File

@@ -23,9 +23,6 @@ class SpringXmlComponentScan extends SpringXmlElement {
string getAProfileExpr() { result = this.getSpringBeanFile().getAProfileExpr() }
}
/** DEPRECATED: Alias for SpringXmlComponentScan */
deprecated class SpringXMLComponentScan = SpringXmlComponentScan;
/**
* An annotation of a class that configures which packages are considered to be "base" packages
* when performing the Spring component scan.

View File

@@ -57,11 +57,6 @@ class SpringRemotingDestinationClass extends Class {
*/
SpringRemotingDestination getRemotingDestinationXml() { this = result.getSpringBean().getClass() }
/** DEPRECATED: Alias for getRemotingDestinationXml */
deprecated SpringRemotingDestination getRemotingDestinationXML() {
result = this.getRemotingDestinationXml()
}
/**
* Holds if the class is operating on an "include" or "exclude" basis.
*

View File

@@ -37,6 +37,3 @@ class SpringXmlElement extends XmlElement {
string getContentString() { result = this.allCharactersString() }
}
/** DEPRECATED: Alias for SpringXmlElement */
deprecated class SpringXMLElement = SpringXmlElement;

View File

@@ -0,0 +1,124 @@
/** Provides classes and predicates related to the Stapler framework. */
import java
private import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.dataflow.FlowSources
private import semmle.code.java.dataflow.FlowSteps
private import semmle.code.java.dataflow.TypeFlow
private import semmle.code.java.frameworks.hudson.Hudson
private import semmle.code.java.frameworks.JavaxAnnotations
/**
* A callable annotated with a Stapler `DataBound` annotation,
* or that has the `@stapler-constructor` Javadoc annotation.
*/
class DataBoundAnnotated extends Callable {
DataBoundAnnotated() {
exists(Annotation an |
an.getType()
.hasQualifiedName("org.kohsuke.stapler", ["DataBoundConstructor", "DataBoundSetter"])
|
this = an.getAnnotatedElement()
)
or
exists(Javadoc doc | doc.getAChild().getText().matches("%@stapler-constructor%") |
doc.getCommentedElement() = this
)
}
}
/** The interface `org.kohsuke.stapler.HttpResponse`. */
class HttpResponse extends Interface {
HttpResponse() { this.hasQualifiedName("org.kohsuke.stapler", "HttpResponse") }
}
/**
* A remote flow source for parameters annotated with an annotation
* that is itself annotated with `InjectedParameter`.
*
* Such parameters are populated with user-provided data by Stapler.
*/
private class InjectedParameterSource extends RemoteFlowSource {
InjectedParameterSource() {
this.asParameter().getAnAnnotation().getType() instanceof InjectedParameterAnnotatedType
}
override string getSourceType() { result = "Stapler injected parameter" }
}
/**
* A dataflow step from the `HttpResponse` return value of a `HudsonWebMethod`
* to the instance parameter of the `generateResponse` method of the appropriate subtype of `HttpResponse`.
*
* This models the rendering process of an `HttpResponse` by Stapler.
*/
private class HttpResponseGetDescriptionStep extends AdditionalValueStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(ReturnStmt s, GenerateResponseMethod m |
s.getEnclosingCallable() instanceof HudsonWebMethod and
boundOrStaticType(s.getResult(), m.getDeclaringType().getADescendant())
|
n1.asExpr() = s.getResult() and
n2.(DataFlow::InstanceParameterNode).getCallable() = m
)
}
}
/**
* A dataflow step from the post-update node of an instance access in a `DataBoundAnnotated` method
* to the instance parameter of a `PostConstruct` method of the same type.
*
* This models the construction process of a `DataBound` object in Stapler.
*/
private class PostConstructDataBoundAdditionalStep extends AdditionalValueStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(PostConstructDataBoundMethod postConstruct, DataBoundAnnotated input |
postConstruct.getDeclaringType() = input.getDeclaringType()
|
n1.(DataFlow::PostUpdateNode)
.getPreUpdateNode()
.(DataFlow::InstanceAccessNode)
.getEnclosingCallable() = input and
n2.(DataFlow::InstanceParameterNode).getCallable() = postConstruct
)
}
}
/** An annotation type annotated with the `InjectedParameter` annotation. */
private class InjectedParameterAnnotatedType extends AnnotationType {
InjectedParameterAnnotatedType() {
this.getAnAnnotation().getType().hasQualifiedName("org.kohsuke.stapler", "InjectedParameter")
}
}
/** The `generateResponse` method of `org.kohsuke.stapler.HttpResponse` or its subtypes. */
private class GenerateResponseMethod extends Method {
GenerateResponseMethod() {
this.getDeclaringType().getASourceSupertype*() instanceof HttpResponse and
this.hasName("generateResponse")
}
}
/** Holds if `t` is the static type of `e`, or an upper bound of the runtime type of `e`. */
private predicate boundOrStaticType(Expr e, RefType t) {
exprTypeFlow(e, t, false)
or
t = e.getType()
}
/**
* A method called after the construction of a `DataBound` object.
*
* That is, either the `bindResolve` method of a subtype of `org.kohsuke.stapler.DataBoundResolvable`,
* or a method annotated with `javax.annotation.PostConstruct`.
*/
private class PostConstructDataBoundMethod extends Method {
PostConstructDataBoundMethod() {
this.getDeclaringType()
.getASourceSupertype*()
.hasQualifiedName("org.kohsuke.stapler", "DataBoundResolvable") and
this.hasName("bindResolve")
or
this.getAnAnnotation() instanceof PostConstructAnnotation
}
}

View File

@@ -77,9 +77,6 @@ StrutsXmlFile getRootXmlFile(RefType refType) {
)
}
/** DEPRECATED: Alias for getRootXmlFile */
deprecated StrutsXMLFile getRootXMLFile(RefType refType) { result = getRootXmlFile(refType) }
/**
* Gets the suffix used for automatically identifying actions when using the convention plugin.
*

View File

@@ -5,9 +5,6 @@ import java
*/
predicate isStrutsXmlIncluded() { exists(StrutsXmlFile strutsXml) }
/** DEPRECATED: Alias for isStrutsXmlIncluded */
deprecated predicate isStrutsXMLIncluded = isStrutsXmlIncluded/0;
/**
* A struts 2 configuration file.
*/
@@ -51,9 +48,6 @@ abstract class StrutsXmlFile extends XmlFile {
}
}
/** DEPRECATED: Alias for StrutsXmlFile */
deprecated class StrutsXMLFile = StrutsXmlFile;
/**
* A Struts 2 "root" configuration XML file directly read by struts.
*
@@ -66,9 +60,6 @@ class StrutsRootXmlFile extends StrutsXmlFile {
}
}
/** DEPRECATED: Alias for StrutsRootXmlFile */
deprecated class StrutsRootXMLFile = StrutsRootXmlFile;
/**
* A Struts 2 configuration XML file included, directly or indirectly, by a root Struts configuration.
*/
@@ -76,9 +67,6 @@ class StrutsIncludedXmlFile extends StrutsXmlFile {
StrutsIncludedXmlFile() { exists(StrutsXmlInclude include | this = include.getIncludedFile()) }
}
/** DEPRECATED: Alias for StrutsIncludedXmlFile */
deprecated class StrutsIncludedXMLFile = StrutsIncludedXmlFile;
/**
* A Folder which has one or more Struts 2 root configurations.
*/
@@ -116,9 +104,6 @@ class StrutsXmlElement extends XmlElement {
string getValue() { result = this.allCharactersString().trim() }
}
/** DEPRECATED: Alias for StrutsXmlElement */
deprecated class StrutsXMLElement = StrutsXmlElement;
/**
* A `<include>` element within a `struts.xml` file.
*
@@ -141,9 +126,6 @@ class StrutsXmlInclude extends StrutsXmlElement {
}
}
/** DEPRECATED: Alias for StrutsXmlInclude */
deprecated class StrutsXMLInclude = StrutsXmlInclude;
/**
* Escape a string for use as the matcher in a string.match(..) call.
*/
@@ -192,9 +174,6 @@ class StrutsXmlAction extends StrutsXmlElement {
}
}
/** DEPRECATED: Alias for StrutsXmlAction */
deprecated class StrutsXMLAction = StrutsXmlAction;
/**
* A `<constant>` property, representing a configuration parameter to struts.
*/
@@ -205,6 +184,3 @@ class StrutsXmlConstant extends StrutsXmlElement {
string getConstantValue() { result = this.getAttribute("value").getValue() }
}
/** DEPRECATED: Alias for StrutsXmlConstant */
deprecated class StrutsXMLConstant = StrutsXmlConstant;

View File

@@ -30,7 +30,7 @@ class IntentRedirectionAdditionalTaintStep extends Unit {
/** Default sink for Intent redirection vulnerabilities. */
private class DefaultIntentRedirectionSink extends IntentRedirectionSink {
DefaultIntentRedirectionSink() { sinkNode(this, "intent-start") }
DefaultIntentRedirectionSink() { sinkNode(this, "intent-redirection") }
}
/**

View File

@@ -20,7 +20,7 @@ private class AndroidFilesystemCleartextStorageSink extends CleartextStorageSink
/** A call to a method or constructor that may write to files to the local filesystem. */
class LocalFileOpenCall extends Storable {
LocalFileOpenCall() {
this = any(DataFlow::Node sink | sinkNode(sink, "create-file")).asExpr().(Argument).getCall()
this = any(DataFlow::Node sink | sinkNode(sink, "path-injection")).asExpr().(Argument).getCall()
}
override Expr getAnInput() {
@@ -40,7 +40,7 @@ class LocalFileOpenCall extends Storable {
/** Holds if `input` is written into `file`. */
private predicate filesystemInput(DataFlow::Node file, Argument input) {
exists(DataFlow::Node write | sinkNode(write, "write-file") |
exists(DataFlow::Node write | sinkNode(write, "file-content-store") |
input = write.asExpr() or
isVarargs(input, write)
) and

View File

@@ -25,9 +25,6 @@ class HttpsUrlConnection extends RefType {
HttpsUrlConnection() { this.hasQualifiedName("javax.net.ssl", "HttpsURLConnection") }
}
/** DEPRECATED: Alias for HttpsUrlConnection */
deprecated class HttpsURLConnection = HttpsUrlConnection;
class SslSocketFactory extends RefType {
SslSocketFactory() { this.hasQualifiedName("javax.net.ssl", "SSLSocketFactory") }
}

View File

@@ -12,9 +12,6 @@ import semmle.code.java.dataflow.TaintTracking
*/
abstract class SafeExternalApiMethod extends Method { }
/** DEPRECATED: Alias for SafeExternalApiMethod */
deprecated class SafeExternalAPIMethod = SafeExternalApiMethod;
/** The default set of "safe" external APIs. */
private class DefaultSafeExternalApiMethod extends SafeExternalApiMethod {
DefaultSafeExternalApiMethod() {
@@ -95,9 +92,6 @@ class ExternalApiDataNode extends DataFlow::Node {
string getMethodDescription() { result = this.getMethod().getQualifiedName() }
}
/** DEPRECATED: Alias for ExternalApiDataNode */
deprecated class ExternalAPIDataNode = ExternalApiDataNode;
/**
* DEPRECATED: Use `UntrustedDataToExternalApiFlow` instead.
*
@@ -125,9 +119,6 @@ module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig {
*/
module UntrustedDataToExternalApiFlow = TaintTracking::Global<UntrustedDataToExternalApiConfig>;
/** DEPRECATED: Alias for UntrustedDataToExternalApiConfig */
deprecated class UntrustedDataToExternalAPIConfig = UntrustedDataToExternalApiConfig;
/** A node representing untrusted data being passed to an external API. */
class UntrustedExternalApiDataNode extends ExternalApiDataNode {
UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::flowTo(this) }
@@ -136,9 +127,6 @@ class UntrustedExternalApiDataNode extends ExternalApiDataNode {
DataFlow::Node getAnUntrustedSource() { UntrustedDataToExternalApiFlow::flow(result, this) }
}
/** DEPRECATED: Alias for UntrustedExternalApiDataNode */
deprecated class UntrustedExternalAPIDataNode = UntrustedExternalApiDataNode;
/** An external API which is used with untrusted data. */
private newtype TExternalApi =
/** An untrusted API method `m` where untrusted data is passed at `index`. */
@@ -172,6 +160,3 @@ class ExternalApiUsedWithUntrustedData extends TExternalApi {
)
}
}
/** DEPRECATED: Alias for ExternalApiUsedWithUntrustedData */
deprecated class ExternalAPIUsedWithUntrustedData = ExternalApiUsedWithUntrustedData;

View File

@@ -21,7 +21,7 @@ class GroovyInjectionAdditionalTaintStep extends Unit {
}
private class DefaultGroovyInjectionSink extends GroovyInjectionSink {
DefaultGroovyInjectionSink() { sinkNode(this, "groovy") }
DefaultGroovyInjectionSink() { sinkNode(this, "groovy-injection") }
}
/** A set of additional taint steps to consider when taint tracking Groovy related data flows. */

View File

@@ -30,7 +30,8 @@ class HttpStringLiteral extends StringLiteral {
abstract class UrlOpenSink extends DataFlow::Node { }
private class DefaultUrlOpenSink extends UrlOpenSink {
DefaultUrlOpenSink() { sinkNode(this, "open-url") }
// request-forgery sinks control the URL of a request
DefaultUrlOpenSink() { sinkNode(this, "request-forgery") }
}
/**

View File

@@ -54,7 +54,8 @@ private class IntentCreationSource extends ImplicitPendingIntentSource {
private class SendPendingIntent extends ImplicitPendingIntentSink {
SendPendingIntent() {
sinkNode(this, "intent-start") and
// intent redirection sinks are method calls that start Android components
sinkNode(this, "intent-redirection") and
// implicit intents can't be started as services since API 21
not exists(MethodAccess ma, Method m |
ma.getMethod() = m and
@@ -63,7 +64,7 @@ private class SendPendingIntent extends ImplicitPendingIntentSink {
this.asExpr() = ma.getArgument(0)
)
or
sinkNode(this, "pending-intent-sent")
sinkNode(this, "pending-intents")
}
override predicate hasState(DataFlow::FlowState state) { state = "MutablePendingIntent" }

View File

@@ -13,7 +13,7 @@ abstract class JexlEvaluationSink extends DataFlow::ExprNode { }
/** Default sink for JXEL injection vulnerabilities. */
private class DefaultJexlEvaluationSink extends JexlEvaluationSink {
DefaultJexlEvaluationSink() { sinkNode(this, "jexl") }
DefaultJexlEvaluationSink() { sinkNode(this, "jexl-injection") }
}
/**

View File

@@ -29,7 +29,7 @@ class LdapInjectionAdditionalTaintStep extends Unit {
/** Default sink for LDAP injection vulnerabilities. */
private class DefaultLdapInjectionSink extends LdapInjectionSink {
DefaultLdapInjectionSink() { sinkNode(this, "ldap") }
DefaultLdapInjectionSink() { sinkNode(this, "ldap-injection") }
}
/** A sanitizer that clears the taint on (boxed) primitive types. */

View File

@@ -27,7 +27,7 @@ class LogInjectionAdditionalTaintStep extends Unit {
}
private class DefaultLogInjectionSink extends LogInjectionSink {
DefaultLogInjectionSink() { sinkNode(this, "logging") }
DefaultLogInjectionSink() { sinkNode(this, "log-injection") }
}
private class DefaultLogInjectionSanitizer extends LogInjectionSanitizer {
@@ -46,16 +46,33 @@ private class LineBreaksLogInjectionSanitizer extends LogInjectionSanitizer {
}
}
private predicate stringMethodAccess(
MethodAccess ma, CompileTimeConstantExpr arg0, CompileTimeConstantExpr arg1
) {
ma.getMethod().getDeclaringType() instanceof TypeString and
arg0 = ma.getArgument(0) and
arg1 = ma.getArgument(1)
}
private predicate stringMethodArgument(CompileTimeConstantExpr arg) {
stringMethodAccess(_, arg, _) or stringMethodAccess(_, _, arg)
}
bindingset[match]
pragma[inline_late]
private predicate stringMethodArgumentValueMatches(CompileTimeConstantExpr const, string match) {
stringMethodArgument(const) and
const.getStringValue().matches(match)
}
/**
* Holds if the return value of `ma` is sanitized against log injection attacks
* by removing line breaks from it.
*/
private predicate logInjectionSanitizer(MethodAccess ma) {
exists(CompileTimeConstantExpr target, CompileTimeConstantExpr replacement |
ma.getMethod().getDeclaringType() instanceof TypeString and
target = ma.getArgument(0) and
replacement = ma.getArgument(1) and
not replacement.getStringValue().matches(["%\n%", "%\r%"])
stringMethodAccess(ma, target, replacement) and
not stringMethodArgumentValueMatches(replacement, ["%\n%", "%\r%"])
|
ma.getMethod().hasName("replace") and
not replacement.getIntValue() = [10, 13] and
@@ -68,7 +85,7 @@ private predicate logInjectionSanitizer(MethodAccess ma) {
(
// Replace anything not in an allow list
target.getStringValue().matches("[^%]") and
not target.getStringValue().matches("%" + ["\n", "\r", "\\n", "\\r", "\\R"] + "%")
not stringMethodArgumentValueMatches(target, "%" + ["\n", "\r", "\\n", "\\r", "\\R"] + "%")
or
// Replace line breaks
target.getStringValue() = ["\n", "\r", "\\n", "\\r", "\\R"]

View File

@@ -25,7 +25,7 @@ class MvelInjectionAdditionalTaintStep extends Unit {
/** Default sink for MVEL injection vulnerabilities. */
private class DefaultMvelEvaluationSink extends MvelEvaluationSink {
DefaultMvelEvaluationSink() { sinkNode(this, "mvel") }
DefaultMvelEvaluationSink() { sinkNode(this, "mvel-injection") }
}
/** A default sanitizer that considers numeric and boolean typed data safe for building MVEL expressions */

View File

@@ -25,7 +25,7 @@ class AdditionalQueryInjectionTaintStep extends Unit {
/** A sink for SQL injection vulnerabilities. */
private class SqlInjectionSink extends QueryInjectionSink {
SqlInjectionSink() { sinkNode(this, "sql") }
SqlInjectionSink() { sinkNode(this, "sql-injection") }
}
/** A sink for Java Persistence Query Language injection vulnerabilities. */

View File

@@ -52,12 +52,8 @@ private class TypePropertiesRequestForgeryAdditionalTaintStep extends RequestFor
/** A data flow sink for server-side request forgery (SSRF) vulnerabilities. */
abstract class RequestForgerySink extends DataFlow::Node { }
private class UrlOpenSinkAsRequestForgerySink extends RequestForgerySink {
UrlOpenSinkAsRequestForgerySink() { sinkNode(this, "open-url") }
}
private class JdbcUrlSinkAsRequestForgerySink extends RequestForgerySink {
JdbcUrlSinkAsRequestForgerySink() { sinkNode(this, "jdbc-url") }
private class DefaultRequestForgerySink extends RequestForgerySink {
DefaultRequestForgerySink() { sinkNode(this, "request-forgery") }
}
/** A sanitizer for request forgery vulnerabilities. */

View File

@@ -11,7 +11,7 @@ private import semmle.code.java.dataflow.ExternalFlow
abstract class HeaderSplittingSink extends DataFlow::Node { }
private class DefaultHeaderSplittingSink extends HeaderSplittingSink {
DefaultHeaderSplittingSink() { sinkNode(this, "header-splitting") }
DefaultHeaderSplittingSink() { sinkNode(this, "response-splitting") }
}
/** A source that introduces data considered safe to use by a header splitting source. */

View File

@@ -5,7 +5,6 @@ private import semmle.code.java.dataflow.ExternalFlow
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.security.SensitiveActions
import semmle.code.java.frameworks.android.Compose
import DataFlow
/** A variable that may hold sensitive information, judging by its name. */
class CredentialExpr extends Expr {
@@ -35,7 +34,7 @@ deprecated class SensitiveLoggerConfiguration extends TaintTracking::Configurati
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof CredentialExpr }
override predicate isSink(DataFlow::Node sink) { sinkNode(sink, "logging") }
override predicate isSink(DataFlow::Node sink) { sinkNode(sink, "log-injection") }
override predicate isSanitizer(DataFlow::Node sanitizer) {
sanitizer.asExpr() instanceof LiveLiteral or
@@ -45,14 +44,14 @@ deprecated class SensitiveLoggerConfiguration extends TaintTracking::Configurati
sanitizer.getType() instanceof TypeType
}
override predicate isSanitizerIn(Node node) { this.isSource(node) }
override predicate isSanitizerIn(DataFlow::Node node) { this.isSource(node) }
}
/** A data-flow configuration for identifying potentially-sensitive data flowing to a log output. */
module SensitiveLoggerConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof CredentialExpr }
predicate isSink(DataFlow::Node sink) { sinkNode(sink, "logging") }
predicate isSink(DataFlow::Node sink) { sinkNode(sink, "log-injection") }
predicate isBarrier(DataFlow::Node sanitizer) {
sanitizer.asExpr() instanceof LiveLiteral or
@@ -62,7 +61,7 @@ module SensitiveLoggerConfig implements DataFlow::ConfigSig {
sanitizer.getType() instanceof TypeType
}
predicate isBarrierIn(Node node) { isSource(node) }
predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
}
module SensitiveLoggerFlow = TaintTracking::Global<SensitiveLoggerConfig>;

View File

@@ -5,7 +5,6 @@ import semmle.code.java.frameworks.Networking
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.FlowSources
private import semmle.code.java.dataflow.ExternalFlow
import semmle.code.java.security.PathCreation
import semmle.code.java.security.PathSanitizer
/**
@@ -55,11 +54,7 @@ private class TaintPreservingUriCtorParam extends Parameter {
module TaintedPathConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) {
sink.asExpr() = any(PathCreation p).getAnInput()
or
sinkNode(sink, ["create-file", "read-file"])
}
predicate isSink(DataFlow::Node sink) { sinkNode(sink, "path-injection") }
predicate isBarrier(DataFlow::Node sanitizer) {
sanitizer.getType() instanceof BoxedType or
@@ -82,11 +77,7 @@ module TaintedPathFlow = TaintTracking::Global<TaintedPathConfig>;
module TaintedPathLocalConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput }
predicate isSink(DataFlow::Node sink) {
sink.asExpr() = any(PathCreation p).getAnInput()
or
sinkNode(sink, "create-file")
}
predicate isSink(DataFlow::Node sink) { sinkNode(sink, "path-injection") }
predicate isBarrier(DataFlow::Node sanitizer) {
sanitizer.getType() instanceof BoxedType or

View File

@@ -66,7 +66,7 @@ private class DefaultTemplateInjectionSource extends TemplateInjectionSource ins
{ }
private class DefaultTemplateInjectionSink extends TemplateInjectionSink {
DefaultTemplateInjectionSink() { sinkNode(this, "ssti") }
DefaultTemplateInjectionSink() { sinkNode(this, "template-injection") }
}
private class DefaultTemplateInjectionSanitizer extends TemplateInjectionSanitizer {

View File

@@ -74,7 +74,7 @@ module TrustAllHostnameVerifierFlow = DataFlow::Global<TrustAllHostnameVerifierC
* A sink that sets the `HostnameVerifier` on `HttpsURLConnection`.
*/
private class HostnameVerifierSink extends DataFlow::Node {
HostnameVerifierSink() { sinkNode(this, "set-hostname-verifier") }
HostnameVerifierSink() { sinkNode(this, "hostname-verification") }
}
/**

View File

@@ -12,7 +12,7 @@ abstract class UrlRedirectSink extends DataFlow::Node { }
/** A default sink represeting methods susceptible to URL redirection attacks. */
private class DefaultUrlRedirectSink extends UrlRedirectSink {
DefaultUrlRedirectSink() { sinkNode(this, "url-redirect") }
DefaultUrlRedirectSink() { sinkNode(this, "url-redirection") }
}
/** A Servlet URL redirection sink. */

View File

@@ -13,7 +13,7 @@ abstract class XPathInjectionSink extends DataFlow::Node { }
/** A default sink representing methods susceptible to XPath Injection attacks. */
private class DefaultXPathInjectionSink extends XPathInjectionSink {
DefaultXPathInjectionSink() {
sinkNode(this, "xpath")
sinkNode(this, "xpath-injection")
or
exists(ClassInstanceExpr constructor |
constructor.getConstructedType().getASourceSupertype*().hasQualifiedName("org.dom4j", "XPath")

View File

@@ -6,6 +6,7 @@ import semmle.code.java.frameworks.android.WebView
import semmle.code.java.frameworks.spring.SpringController
import semmle.code.java.frameworks.spring.SpringHttp
import semmle.code.java.frameworks.javaee.jsf.JSFRenderer
private import semmle.code.java.frameworks.hudson.Hudson
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.TaintTracking
private import semmle.code.java.dataflow.ExternalFlow
@@ -39,7 +40,7 @@ class XssAdditionalTaintStep extends Unit {
/** A default sink representing methods susceptible to XSS attacks. */
private class DefaultXssSink extends XssSink {
DefaultXssSink() {
sinkNode(this, "xss")
sinkNode(this, ["html-injection", "js-injection"])
or
exists(MethodAccess ma |
ma.getMethod() instanceof WritingMethod and

View File

@@ -337,9 +337,6 @@ class SaxBuilder extends RefType {
}
}
/** DEPRECATED: Alias for SaxBuilder */
deprecated class SAXBuilder = SaxBuilder;
/**
* A call to `SAXBuilder.build.`
*/
@@ -359,9 +356,6 @@ class SaxBuilderParse extends XmlParserCall {
}
}
/** DEPRECATED: Alias for SaxBuilderParse */
deprecated class SAXBuilderParse = SaxBuilderParse;
private module SafeSaxBuilderToSaxBuilderParseFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeSaxBuilder }
@@ -386,9 +380,6 @@ class SaxBuilderConfig extends ParserConfig {
}
}
/** DEPRECATED: Alias for SaxBuilderConfig */
deprecated class SAXBuilderConfig = SaxBuilderConfig;
/** A safely configured `SaxBuilder`. */
class SafeSaxBuilder extends VarAccess {
SafeSaxBuilder() {
@@ -404,9 +395,6 @@ class SafeSaxBuilder extends VarAccess {
}
}
/** DEPRECATED: Alias for SafeSaxBuilder */
deprecated class SafeSAXBuilder = SafeSaxBuilder;
/*
* The case in
* https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxb-unmarshaller
@@ -420,17 +408,11 @@ class SaxParser extends RefType {
SaxParser() { this.hasQualifiedName("javax.xml.parsers", "SAXParser") }
}
/** DEPRECATED: Alias for SaxParser */
deprecated class SAXParser = SaxParser;
/** The class `javax.xml.parsers.SAXParserFactory`. */
class SaxParserFactory extends RefType {
SaxParserFactory() { this.hasQualifiedName("javax.xml.parsers", "SAXParserFactory") }
}
/** DEPRECATED: Alias for SaxParserFactory */
deprecated class SAXParserFactory = SaxParserFactory;
/** A call to `SAXParser.parse`. */
class SaxParserParse extends XmlParserCall {
SaxParserParse() {
@@ -446,9 +428,6 @@ class SaxParserParse extends XmlParserCall {
override predicate isSafe() { SafeSaxParserFlow::flowToExpr(this.getQualifier()) }
}
/** DEPRECATED: Alias for SaxParserParse */
deprecated class SAXParserParse = SaxParserParse;
/** A `ParserConfig` that is specific to `SaxParserFactory`. */
class SaxParserFactoryConfig extends ParserConfig {
SaxParserFactoryConfig() {
@@ -460,9 +439,6 @@ class SaxParserFactoryConfig extends ParserConfig {
}
}
/** DEPRECATED: Alias for SaxParserFactoryConfig */
deprecated class SAXParserFactoryConfig = SaxParserFactoryConfig;
/**
* A safely configured `SAXParserFactory`.
*/
@@ -496,9 +472,6 @@ class SafeSaxParserFactory extends VarAccess {
}
}
/** DEPRECATED: Alias for SafeSaxParserFactory */
deprecated class SafeSAXParserFactory = SafeSaxParserFactory;
private module SafeSaxParserFactoryToNewSaxParserFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeSaxParserFactory }
@@ -540,9 +513,6 @@ class SafeSaxParser extends MethodAccess {
}
}
/** DEPRECATED: Alias for SafeSaxParser */
deprecated class SafeSAXParser = SafeSaxParser;
/* SAXReader: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#saxreader */
/**
* The class `org.dom4j.io.SAXReader`.
@@ -551,9 +521,6 @@ class SaxReader extends RefType {
SaxReader() { this.hasQualifiedName("org.dom4j.io", "SAXReader") }
}
/** DEPRECATED: Alias for SaxReader */
deprecated class SAXReader = SaxReader;
/** A call to `SAXReader.read`. */
class SaxReaderRead extends XmlParserCall {
SaxReaderRead() {
@@ -569,9 +536,6 @@ class SaxReaderRead extends XmlParserCall {
override predicate isSafe() { SafeSaxReaderFlow::flowToExpr(this.getQualifier()) }
}
/** DEPRECATED: Alias for SaxReaderRead */
deprecated class SAXReaderRead = SaxReaderRead;
/** A `ParserConfig` specific to `SaxReader`. */
class SaxReaderConfig extends ParserConfig {
SaxReaderConfig() {
@@ -583,9 +547,6 @@ class SaxReaderConfig extends ParserConfig {
}
}
/** DEPRECATED: Alias for SaxReaderConfig */
deprecated class SAXReaderConfig = SaxReaderConfig;
private module SafeSaxReaderFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeSaxReader }
@@ -626,9 +587,6 @@ class SafeSaxReader extends VarAccess {
}
}
/** DEPRECATED: Alias for SafeSaxReader */
deprecated class SafeSAXReader = SafeSaxReader;
/* https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xmlreader */
/** The class `org.xml.sax.XMLReader`. */
class XmlReader extends RefType {
@@ -640,9 +598,6 @@ class InputSource extends Class {
InputSource() { this.hasQualifiedName("org.xml.sax", "InputSource") }
}
/** DEPRECATED: Alias for XmlReader */
deprecated class XMLReader = XmlReader;
/** A call to `XMLReader.read`. */
class XmlReaderParse extends XmlParserCall {
XmlReaderParse() {
@@ -661,9 +616,6 @@ class XmlReaderParse extends XmlParserCall {
}
}
/** DEPRECATED: Alias for XmlReaderParse */
deprecated class XMLReaderParse = XmlReaderParse;
/** A `ParserConfig` specific to the `XmlReader`. */
class XmlReaderConfig extends ParserConfig {
XmlReaderConfig() {
@@ -675,9 +627,6 @@ class XmlReaderConfig extends ParserConfig {
}
}
/** DEPRECATED: Alias for XmlReaderConfig */
deprecated class XMLReaderConfig = XmlReaderConfig;
private module ExplicitlySafeXmlReaderFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ExplicitlySafeXmlReader }
@@ -697,9 +646,6 @@ class SafeXmlReaderFlowSink extends Expr {
}
}
/** DEPRECATED: Alias for SafeXmlReaderFlowSink */
deprecated class SafeXMLReaderFlowSink = SafeXmlReaderFlowSink;
/** An `XmlReader` that is explicitly configured to be safe. */
class ExplicitlySafeXmlReader extends VarAccess {
ExplicitlySafeXmlReader() {
@@ -739,9 +685,6 @@ class ExplicitlySafeXmlReader extends VarAccess {
}
}
/** DEPRECATED: Alias for ExplicitlySafeXmlReader */
deprecated class ExplicitlySafeXMLReader = ExplicitlySafeXmlReader;
private module CreatedSafeXmlReaderFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof CreatedSafeXmlReader }
@@ -778,9 +721,6 @@ class CreatedSafeXmlReader extends Call {
}
}
/** DEPRECATED: Alias for CreatedSafeXmlReader */
deprecated class CreatedSafeXMLReader = CreatedSafeXmlReader;
/*
* SAXSource in
* https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxb-unmarshaller
@@ -791,9 +731,6 @@ class SaxSource extends RefType {
SaxSource() { this.hasQualifiedName("javax.xml.transform.sax", "SAXSource") }
}
/** DEPRECATED: Alias for SaxSource */
deprecated class SAXSource = SaxSource;
/** A call to the constructor of `SAXSource` with `XmlReader` and `InputSource`. */
class ConstructedSaxSource extends ClassInstanceExpr {
ConstructedSaxSource() {
@@ -814,9 +751,6 @@ class ConstructedSaxSource extends ClassInstanceExpr {
}
}
/** DEPRECATED: Alias for ConstructedSaxSource */
deprecated class ConstructedSAXSource = ConstructedSaxSource;
/** A call to the `SAXSource.setXMLReader` method. */
class SaxSourceSetReader extends MethodAccess {
SaxSourceSetReader() {
@@ -828,9 +762,6 @@ class SaxSourceSetReader extends MethodAccess {
}
}
/** DEPRECATED: Alias for SaxSourceSetReader */
deprecated class SAXSourceSetReader = SaxSourceSetReader;
/** A `SaxSource` that is safe to use. */
class SafeSaxSource extends Expr {
SafeSaxSource() {
@@ -847,9 +778,6 @@ class SafeSaxSource extends Expr {
}
}
/** DEPRECATED: Alias for SafeSaxSource */
deprecated class SafeSAXSource = SafeSaxSource;
/* Transformer: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#transformerfactory */
/** An access to a method use for configuring a transformer or schema. */
abstract class TransformerConfig extends MethodAccess {
@@ -1063,9 +991,6 @@ class SaxTransformerFactoryNewXmlFilter extends XmlParserCall {
override predicate isSafe() { SafeTransformerFactoryFlow::flowToExpr(this.getQualifier()) }
}
/** DEPRECATED: Alias for SaxTransformerFactoryNewXmlFilter */
deprecated class SAXTransformerFactoryNewXMLFilter = SaxTransformerFactoryNewXmlFilter;
/* Schema: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#schemafactory */
/** The class `javax.xml.validation.SchemaFactory`. */
class SchemaFactory extends RefType {
@@ -1197,9 +1122,6 @@ class SimpleXmlPersisterCall extends XmlParserCall {
override predicate isSafe() { none() }
}
/** DEPRECATED: Alias for SimpleXmlPersisterCall */
deprecated class SimpleXMLPersisterCall = SimpleXmlPersisterCall;
/** A call to `provide` in `Provider`. */
class SimpleXmlProviderCall extends XmlParserCall {
SimpleXmlProviderCall() {
@@ -1218,9 +1140,6 @@ class SimpleXmlProviderCall extends XmlParserCall {
override predicate isSafe() { none() }
}
/** DEPRECATED: Alias for SimpleXmlProviderCall */
deprecated class SimpleXMLProviderCall = SimpleXmlProviderCall;
/** A call to `read` in `NodeBuilder`. */
class SimpleXmlNodeBuilderCall extends XmlParserCall {
SimpleXmlNodeBuilderCall() {
@@ -1236,9 +1155,6 @@ class SimpleXmlNodeBuilderCall extends XmlParserCall {
override predicate isSafe() { none() }
}
/** DEPRECATED: Alias for SimpleXmlNodeBuilderCall */
deprecated class SimpleXMLNodeBuilderCall = SimpleXmlNodeBuilderCall;
/** A call to the `format` method of the `Formatter`. */
class SimpleXmlFormatterCall extends XmlParserCall {
SimpleXmlFormatterCall() {
@@ -1254,9 +1170,6 @@ class SimpleXmlFormatterCall extends XmlParserCall {
override predicate isSafe() { none() }
}
/** DEPRECATED: Alias for SimpleXmlFormatterCall */
deprecated class SimpleXMLFormatterCall = SimpleXmlFormatterCall;
/** A configuration for secure processing. */
Expr configSecureProcessing() {
result.(ConstantStringExpr).getStringValue() =

View File

@@ -12,7 +12,7 @@ abstract class XsltInjectionSink extends DataFlow::Node { }
/** A default sink representing methods susceptible to XSLT Injection attacks. */
private class DefaultXsltInjectionSink extends XsltInjectionSink {
DefaultXsltInjectionSink() { sinkNode(this, "xslt") }
DefaultXsltInjectionSink() { sinkNode(this, "xslt-injection") }
}
/**

View File

@@ -4,6 +4,7 @@ import java
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.security.PathSanitizer
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.security.PathCreation
/**
* A method that returns the name of an archive entry.
@@ -40,5 +41,28 @@ module ZipSlipFlow = TaintTracking::Global<ZipSlipConfig>;
* A sink that represents a file creation, such as a file write, copy or move operation.
*/
private class FileCreationSink extends DataFlow::Node {
FileCreationSink() { sinkNode(this, "create-file") }
FileCreationSink() {
sinkNode(this, "path-injection") and
not isPathCreation(this)
}
}
/**
* Holds if `sink` is a path creation node that doesn't imply a read/write filesystem operation.
* This is to avoid creating new spurious alerts, since `PathCreation` sinks weren't
* previously part of this query.
*/
private predicate isPathCreation(DataFlow::Node sink) {
exists(PathCreation pc |
pc.getAnInput() = sink.asExpr()
or
pc.getAnInput().(Argument).isVararg() and sink.(DataFlow::ImplicitVarargsArray).getCall() = pc
|
// exclude actual read/write operations included in `PathCreation`
not pc.(Call)
.getCallee()
.getDeclaringType()
.hasQualifiedName("java.io",
["FileInputStream", "FileOutputStream", "FileReader", "FileWriter"])
)
}