mirror of
https://github.com/github/codeql.git
synced 2026-04-30 03:05:15 +02:00
python: sync files and fix many small things
- but now we have non-monotonic recursion again...
This commit is contained in:
@@ -47,37 +47,10 @@ module SummaryComponentStack {
|
||||
}
|
||||
|
||||
/** A callable with a flow summary, identified by a unique string. */
|
||||
abstract class SummarizedCallable extends LibraryCallable {
|
||||
abstract class SummarizedCallable extends LibraryCallable, Impl::Public::SummarizedCallable {
|
||||
bindingset[this]
|
||||
SummarizedCallable() { any() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `input` to `output` through this callable.
|
||||
*
|
||||
* `preservesValue` indicates whether this is a value-preserving step
|
||||
* or a taint-step.
|
||||
*
|
||||
* Input specifications are restricted to stacks that end with
|
||||
* `SummaryComponent::argument(_)`, preceded by zero or more
|
||||
* `SummaryComponent::return()` or `SummaryComponent::content(_)` components.
|
||||
*
|
||||
* Output specifications are restricted to stacks that end with
|
||||
* `SummaryComponent::return()` or `SummaryComponent::argument(_)`.
|
||||
*
|
||||
* Output stacks ending with `SummaryComponent::return()` can be preceded by zero
|
||||
* or more `SummaryComponent::content(_)` components.
|
||||
*
|
||||
* Output stacks ending with `SummaryComponent::argument(_)` can be preceded by an
|
||||
* optional `SummaryComponent::parameter(_)` component, which in turn can be preceded
|
||||
* by zero or more `SummaryComponent::content(_)` components.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate propagatesFlow(
|
||||
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
|
||||
) {
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as
|
||||
*
|
||||
@@ -91,29 +64,35 @@ abstract class SummarizedCallable extends LibraryCallable {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate propagatesFlowExt(string input, string output, boolean preservesValue) { none() }
|
||||
|
||||
/**
|
||||
* Holds if values stored inside `content` are cleared on objects passed as
|
||||
* arguments at position `pos` to this callable.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) { none() }
|
||||
}
|
||||
|
||||
private class SummarizedCallableAdapter extends Impl::Public::SummarizedCallable {
|
||||
private SummarizedCallable sc;
|
||||
|
||||
SummarizedCallableAdapter() { this = TLibraryCallable(sc) }
|
||||
|
||||
final override predicate propagatesFlow(
|
||||
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
|
||||
) {
|
||||
sc.propagatesFlow(input, output, preservesValue)
|
||||
}
|
||||
|
||||
final override predicate clearsContent(ParameterPosition pos, DataFlow::ContentSet content) {
|
||||
sc.clearsContent(pos, content)
|
||||
}
|
||||
}
|
||||
|
||||
class RequiredSummaryComponentStack = Impl::Public::RequiredSummaryComponentStack;
|
||||
//
|
||||
// TODO: Implement this
|
||||
//
|
||||
// private class SummarizedCallableFromModel extends SummarizedCallable {
|
||||
// string package;
|
||||
// string type;
|
||||
// string path;
|
||||
// SummarizedCallableFromModel() {
|
||||
// ModelOutput::relevantSummaryModel(package, type, path, _, _, _) and
|
||||
// this = package + ";" + type + ";" + path
|
||||
// }
|
||||
// override Call getACall() {
|
||||
// exists(API::MethodAccessNode base |
|
||||
// ModelOutput::resolvedSummaryBase(package, type, path, base) and
|
||||
// result = base.getCallNode().asExpr().getExpr()
|
||||
// )
|
||||
// }
|
||||
// override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
|
||||
// exists(string kind |
|
||||
// ModelOutput::relevantSummaryModel(package, type, path, input, output, kind)
|
||||
// |
|
||||
// kind = "value" and
|
||||
// preservesValue = true
|
||||
// or
|
||||
// kind = "taint" and
|
||||
// preservesValue = false
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -40,7 +40,7 @@ abstract class AttrRef extends Node {
|
||||
or
|
||||
exists(LocalSourceNode nodeFrom |
|
||||
nodeFrom.flowsTo(this.getAttributeNameExpr()) and
|
||||
attrName = nodeFrom.asExpr().(StrConst).getText()
|
||||
attrName = nodeFrom.(CfgNode).getNode().getNode().(StrConst).getText()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ private class SetAttrCallAsAttrWrite extends AttrWrite, CfgNode {
|
||||
override ExprNode getAttributeNameExpr() { result.asCfgNode() = node.getName() }
|
||||
|
||||
override string getAttributeName() {
|
||||
result = this.getAttributeNameExpr().asExpr().(StrConst).getText()
|
||||
result = this.getAttributeNameExpr().(CfgNode).getNode().getNode().(StrConst).getText()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ private class GetAttrCallAsAttrRead extends AttrRead, CfgNode {
|
||||
override ExprNode getAttributeNameExpr() { result.asCfgNode() = node.getName() }
|
||||
|
||||
override string getAttributeName() {
|
||||
result = this.getAttributeNameExpr().asExpr().(StrConst).getText()
|
||||
result = this.getAttributeNameExpr().(CfgNode).getNode().getNode().(StrConst).getText()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -656,7 +656,7 @@ class SummaryCall extends DataFlowCall, TSummaryCall {
|
||||
/** Gets the data flow node that this call targets. */
|
||||
Node getReceiver() { result = receiver }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() { result = c }
|
||||
override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = c }
|
||||
|
||||
override DataFlowCallable getCallable() { none() }
|
||||
|
||||
@@ -666,7 +666,7 @@ class SummaryCall extends DataFlowCall, TSummaryCall {
|
||||
|
||||
override string toString() { result = "[summary] call to " + receiver + " in " + c }
|
||||
|
||||
override Location getLocation() { result = c.getLocation() }
|
||||
override Location getLocation() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -692,9 +692,11 @@ class SummaryParameterNode extends ParameterNodeImpl, TSummaryParameterNode {
|
||||
|
||||
override Parameter getParameter() { none() }
|
||||
|
||||
override predicate isParameterOf(DataFlowCallable c, int i) { sc = c and i = pos }
|
||||
override predicate isParameterOf(DataFlowCallable c, int i) {
|
||||
sc = c.asLibraryCallable() and i = pos
|
||||
}
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() { result = sc }
|
||||
override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = sc }
|
||||
}
|
||||
|
||||
/** A data-flow node used to model flow summaries. */
|
||||
@@ -704,7 +706,7 @@ class SummaryNode extends Node, TSummaryNode {
|
||||
|
||||
SummaryNode() { this = TSummaryNode(c, state) }
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() { result = c }
|
||||
override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = c }
|
||||
|
||||
override string toString() { result = "[summary] " + state + " in " + c }
|
||||
}
|
||||
|
||||
@@ -417,7 +417,7 @@ class ModuleVariableNode extends Node, TModuleVariableNode {
|
||||
|
||||
/** Gets an `EssaNode` that corresponds to an assignment of this global variable. */
|
||||
EssaNode getAWrite() {
|
||||
result.asVar().getDefinition().(EssaNodeDefinition).definedBy(var, any(DefinitionNode defn))
|
||||
result.getVar().getDefinition().(EssaNodeDefinition).definedBy(var, any(DefinitionNode defn))
|
||||
}
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() { result.(DataFlowModuleScope).getScope() = mod }
|
||||
|
||||
@@ -16,7 +16,7 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
or
|
||||
// Simple flow through library code is included in the exposed local
|
||||
// step relation, even though flow is technically inter-procedural
|
||||
FlowSummaryImpl::Private::Steps::summaryThroughStep(nodeFrom, nodeTo, true)
|
||||
FlowSummaryImpl::Private::Steps::summaryThroughStepValue(nodeFrom, nodeTo, _)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -195,7 +195,10 @@ module Public {
|
||||
}
|
||||
|
||||
/** A callable with a flow summary. */
|
||||
abstract class SummarizedCallable extends DataFlowCallable {
|
||||
abstract class SummarizedCallable extends SummarizedCallableBase {
|
||||
bindingset[this]
|
||||
SummarizedCallable() { any() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `input` to `output` through this callable.
|
||||
*
|
||||
@@ -493,7 +496,7 @@ module Private {
|
||||
or
|
||||
exists(ParameterPosition pos |
|
||||
parameterReadState(c, state, pos) and
|
||||
result.(ParamNode).isParameterOf(c, pos)
|
||||
result.(ParamNode).isParameterOf(inject(c), pos)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -621,7 +624,7 @@ module Private {
|
||||
predicate summaryPostUpdateNode(Node post, Node pre) {
|
||||
exists(SummarizedCallable c, ParameterPosition pos |
|
||||
isParameterPostUpdate(post, c, pos) and
|
||||
pre.(ParamNode).isParameterOf(c, pos)
|
||||
pre.(ParamNode).isParameterOf(inject(c), pos)
|
||||
)
|
||||
or
|
||||
exists(SummarizedCallable callable, SummaryComponentStack s |
|
||||
@@ -644,7 +647,7 @@ module Private {
|
||||
* node, and back out to `p`.
|
||||
*/
|
||||
predicate summaryAllowParameterReturnInSelf(ParamNode p) {
|
||||
exists(SummarizedCallable c, ParameterPosition ppos | p.isParameterOf(c, ppos) |
|
||||
exists(SummarizedCallable c, ParameterPosition ppos | p.isParameterOf(inject(c), ppos) |
|
||||
exists(SummaryComponentStack inputContents, SummaryComponentStack outputContents |
|
||||
summary(c, inputContents, outputContents, _) and
|
||||
inputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(ppos)) and
|
||||
@@ -748,13 +751,16 @@ module Private {
|
||||
private predicate viableParam(
|
||||
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, ParamNode p
|
||||
) {
|
||||
p.isParameterOf(sc, ppos) and
|
||||
sc = viableCallable(call)
|
||||
exists(DataFlowCallable c |
|
||||
c = inject(sc) and
|
||||
p.isParameterOf(c, ppos) and
|
||||
c = viableCallable(call)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private ParamNode summaryArgParam0(DataFlowCall call, ArgNode arg) {
|
||||
exists(ParameterPosition ppos, SummarizedCallable sc |
|
||||
private ParamNode summaryArgParam0(DataFlowCall call, ArgNode arg, SummarizedCallable sc) {
|
||||
exists(ParameterPosition ppos |
|
||||
argumentPositionMatch(call, arg, ppos) and
|
||||
viableParam(call, sc, ppos, result)
|
||||
)
|
||||
@@ -768,41 +774,56 @@ module Private {
|
||||
* or expects contents.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate prohibitsUseUseFlow(ArgNode arg) {
|
||||
predicate prohibitsUseUseFlow(ArgNode arg, SummarizedCallable sc) {
|
||||
exists(ParamNode p, Node mid, ParameterPosition ppos, Node ret |
|
||||
p = summaryArgParam0(_, arg) and
|
||||
p.isParameterOf(_, ppos) and
|
||||
p = summaryArgParam0(_, arg, sc) and
|
||||
p.isParameterOf(_, pragma[only_bind_into](ppos)) and
|
||||
summaryLocalStep(p, mid, true) and
|
||||
summaryLocalStep(mid, ret, true) and
|
||||
isParameterPostUpdate(ret, _, ppos)
|
||||
isParameterPostUpdate(ret, _, pragma[only_bind_into](ppos))
|
||||
|
|
||||
summaryClearsContent(mid, _) or
|
||||
summaryExpectsContent(mid, _)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private ParamNode summaryArgParam(ArgNode arg, ReturnKindExt rk, OutNodeExt out) {
|
||||
exists(DataFlowCall call |
|
||||
result = summaryArgParam0(call, arg) and
|
||||
out = rk.getAnOutNode(call)
|
||||
bindingset[ret]
|
||||
private ParamNode summaryArgParam(
|
||||
ArgNode arg, ReturnNodeExt ret, OutNodeExt out, SummarizedCallable sc
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKindExt rk |
|
||||
result = summaryArgParam0(call, arg, sc) and
|
||||
ret.getKind() = pragma[only_bind_into](rk) and
|
||||
out = pragma[only_bind_into](rk).getAnOutNode(call)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` flows to `out` using a simple flow summary, that is, a flow
|
||||
* summary without reads and stores.
|
||||
* Holds if `arg` flows to `out` using a simple value-preserving flow
|
||||
* summary, that is, a flow summary without reads and stores.
|
||||
*
|
||||
* NOTE: This step should not be used in global data-flow/taint-tracking, but may
|
||||
* be useful to include in the exposed local data-flow/taint-tracking relations.
|
||||
*/
|
||||
predicate summaryThroughStep(ArgNode arg, Node out, boolean preservesValue) {
|
||||
exists(ReturnKindExt rk, ReturnNodeExt ret |
|
||||
summaryLocalStep(summaryArgParam(arg, rk, out), ret, preservesValue) and
|
||||
ret.getKind() = rk
|
||||
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
|
||||
out = getAnOutNode(call, pragma[only_bind_into](rk))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` flows to `out` using a simple flow summary involving taint
|
||||
* step, that is, a flow summary without reads and stores.
|
||||
*
|
||||
* NOTE: This step should not be used in global data-flow/taint-tracking, but may
|
||||
* 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))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a read(+taint) of `c` from `arg` to `out` using a
|
||||
* flow summary.
|
||||
@@ -810,11 +831,10 @@ module Private {
|
||||
* NOTE: This step should not be used in global data-flow/taint-tracking, but may
|
||||
* be useful to include in the exposed local data-flow/taint-tracking relations.
|
||||
*/
|
||||
predicate summaryGetterStep(ArgNode arg, ContentSet c, Node out) {
|
||||
exists(ReturnKindExt rk, Node mid, ReturnNodeExt ret |
|
||||
summaryReadStep(summaryArgParam(arg, rk, out), c, mid) and
|
||||
summaryLocalStep(mid, ret, _) and
|
||||
ret.getKind() = rk
|
||||
predicate summaryGetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
|
||||
exists(Node mid, ReturnNodeExt ret |
|
||||
summaryReadStep(summaryArgParam(arg, ret, out, sc), c, mid) and
|
||||
summaryLocalStep(mid, ret, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -825,11 +845,10 @@ module Private {
|
||||
* NOTE: This step should not be used in global data-flow/taint-tracking, but may
|
||||
* be useful to include in the exposed local data-flow/taint-tracking relations.
|
||||
*/
|
||||
predicate summarySetterStep(ArgNode arg, ContentSet c, Node out) {
|
||||
exists(ReturnKindExt rk, Node mid, ReturnNodeExt ret |
|
||||
summaryLocalStep(summaryArgParam(arg, rk, out), mid, _) and
|
||||
summaryStoreStep(mid, c, ret) and
|
||||
ret.getKind() = rk
|
||||
predicate summarySetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
|
||||
exists(Node mid, ReturnNodeExt ret |
|
||||
summaryLocalStep(summaryArgParam(arg, ret, out, sc), mid, _) and
|
||||
summaryStoreStep(mid, c, ret)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -912,11 +931,18 @@ module Private {
|
||||
private class SummarizedCallableExternal extends SummarizedCallable {
|
||||
SummarizedCallableExternal() { summaryElement(this, _, _, _, _) }
|
||||
|
||||
private predicate relevantSummaryElementGenerated(
|
||||
AccessPath inSpec, AccessPath outSpec, string kind
|
||||
) {
|
||||
summaryElement(this, inSpec, outSpec, kind, true) and
|
||||
not summaryElement(this, _, _, _, false) and
|
||||
not this.clearsContent(_, _)
|
||||
}
|
||||
|
||||
private predicate relevantSummaryElement(AccessPath inSpec, AccessPath outSpec, string kind) {
|
||||
summaryElement(this, inSpec, outSpec, kind, false)
|
||||
or
|
||||
summaryElement(this, inSpec, outSpec, kind, true) and
|
||||
not summaryElement(this, _, _, _, false)
|
||||
this.relevantSummaryElementGenerated(inSpec, outSpec, kind)
|
||||
}
|
||||
|
||||
override predicate propagatesFlow(
|
||||
@@ -933,7 +959,7 @@ module Private {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isAutoGenerated() { summaryElement(this, _, _, _, true) }
|
||||
override predicate isAutoGenerated() { this.relevantSummaryElementGenerated(_, _, _) }
|
||||
}
|
||||
|
||||
/** Holds if component `c` of specification `spec` cannot be parsed. */
|
||||
@@ -1069,7 +1095,7 @@ module Private {
|
||||
/** Provides a query predicate for outputting a set of relevant flow summaries. */
|
||||
module TestOutput {
|
||||
/** A flow summary to include in the `summary/3` query predicate. */
|
||||
abstract class RelevantSummarizedCallable extends SummarizedCallable {
|
||||
abstract class RelevantSummarizedCallable instanceof SummarizedCallable {
|
||||
/** Gets the string representation of this callable used by `summary/1`. */
|
||||
abstract string getCallableCsv();
|
||||
|
||||
@@ -1077,8 +1103,10 @@ module Private {
|
||||
predicate relevantSummary(
|
||||
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
|
||||
) {
|
||||
this.propagatesFlow(input, output, preservesValue)
|
||||
super.propagatesFlow(input, output, preservesValue)
|
||||
}
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
}
|
||||
|
||||
/** Render the kind in the format used in flow summaries. */
|
||||
@@ -1088,13 +1116,13 @@ module Private {
|
||||
preservesValue = false and result = "taint"
|
||||
}
|
||||
|
||||
private string renderGenerated(RelevantSummarizedCallable c) {
|
||||
if c.isAutoGenerated() then result = "generated:" else result = ""
|
||||
private string renderProvenance(RelevantSummarizedCallable c) {
|
||||
if c.(SummarizedCallable).isAutoGenerated() then result = "generated" else result = "manual"
|
||||
}
|
||||
|
||||
/**
|
||||
* A query predicate for outputting flow summaries in semi-colon separated format in QL tests.
|
||||
* The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;(generated:)?kind",
|
||||
* The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind;provenance"",
|
||||
* ext is hardcoded to empty.
|
||||
*/
|
||||
query predicate summary(string csv) {
|
||||
@@ -1105,7 +1133,7 @@ module Private {
|
||||
c.relevantSummary(input, output, preservesValue) and
|
||||
csv =
|
||||
c.getCallableCsv() + getComponentStackCsv(input) + ";" + getComponentStackCsv(output) +
|
||||
";" + renderGenerated(c) + renderKind(preservesValue)
|
||||
";" + renderKind(preservesValue) + ";" + renderProvenance(c)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1119,19 +1147,21 @@ module Private {
|
||||
*/
|
||||
module RenderSummarizedCallable {
|
||||
/** A summarized callable to include in the graph. */
|
||||
abstract class RelevantSummarizedCallable extends SummarizedCallable { }
|
||||
abstract class RelevantSummarizedCallable instanceof SummarizedCallable {
|
||||
string toString() { result = super.toString() }
|
||||
}
|
||||
|
||||
private newtype TNodeOrCall =
|
||||
MkNode(Node n) {
|
||||
exists(RelevantSummarizedCallable c |
|
||||
n = summaryNode(c, _)
|
||||
or
|
||||
n.(ParamNode).isParameterOf(c, _)
|
||||
n.(ParamNode).isParameterOf(inject(c), _)
|
||||
)
|
||||
} or
|
||||
MkCall(DataFlowCall call) {
|
||||
call = summaryDataFlowCall(_) and
|
||||
call.getEnclosingCallable() instanceof RelevantSummarizedCallable
|
||||
call.getEnclosingCallable() = inject(any(RelevantSummarizedCallable c))
|
||||
}
|
||||
|
||||
private class NodeOrCall extends TNodeOrCall {
|
||||
|
||||
@@ -10,6 +10,10 @@ private import FlowSummaryImpl::Private
|
||||
private import FlowSummaryImpl::Public
|
||||
private import semmle.python.dataflow.new.FlowSummary as FlowSummary
|
||||
|
||||
class SummarizedCallableBase = string;
|
||||
|
||||
DataFlowCallable inject(SummarizedCallable c) { result.asLibraryCallable() = c }
|
||||
|
||||
/** Gets the parameter position of the instance parameter. */
|
||||
ArgumentPosition instanceParameterPosition() { none() } // disables implicit summary flow to `this` for callbacks
|
||||
|
||||
@@ -45,11 +49,10 @@ DataFlowType getCallbackReturnType(DataFlowType t, ReturnKind rk) { any() }
|
||||
* stating whether the summary is autogenerated.
|
||||
*/
|
||||
predicate summaryElement(
|
||||
DataFlowCallable c, string input, string output, string kind, boolean generated
|
||||
FlowSummary::SummarizedCallable c, string input, string output, string kind, boolean generated
|
||||
) {
|
||||
exists(FlowSummary::SummarizedCallable sc, boolean preservesValue |
|
||||
sc.propagatesFlowExt(input, output, preservesValue) and
|
||||
c.asLibraryCallable() = sc and
|
||||
exists(boolean preservesValue |
|
||||
c.propagatesFlowExt(input, output, preservesValue) and
|
||||
(if preservesValue = true then kind = "value" else kind = "taint") and
|
||||
generated = false
|
||||
)
|
||||
|
||||
@@ -244,7 +244,7 @@ class UnpackingAssignmentSequenceTarget extends UnpackingAssignmentTarget instan
|
||||
*/
|
||||
predicate iterableUnpackingAssignmentFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(AssignmentTarget target |
|
||||
nodeFrom.asExpr() = target.getValue() and
|
||||
nodeFrom.(CfgNode).getNode().getNode() = target.getValue() and
|
||||
nodeTo = TIterableSequenceNode(target)
|
||||
)
|
||||
}
|
||||
@@ -255,7 +255,7 @@ predicate iterableUnpackingAssignmentFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
*/
|
||||
predicate iterableUnpackingForReadStep(CfgNode nodeFrom, Content c, Node nodeTo) {
|
||||
exists(ForTarget target |
|
||||
nodeFrom.asExpr() = target.getSource() and
|
||||
nodeFrom.(CfgNode).getNode().getNode() = target.getSource() and
|
||||
target instanceof SequenceNode and
|
||||
nodeTo = TIterableSequenceNode(target)
|
||||
) and
|
||||
@@ -273,7 +273,7 @@ predicate iterableUnpackingForReadStep(CfgNode nodeFrom, Content c, Node nodeTo)
|
||||
predicate iterableUnpackingTupleFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(UnpackingAssignmentSequenceTarget target |
|
||||
nodeFrom = TIterableSequenceNode(target) and
|
||||
nodeTo.asCfgNode() = target
|
||||
nodeTo.(CfgNode).getNode() = target
|
||||
)
|
||||
}
|
||||
|
||||
@@ -305,7 +305,7 @@ predicate iterableUnpackingConvertingReadStep(Node nodeFrom, Content c, Node nod
|
||||
predicate iterableUnpackingConvertingStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(UnpackingAssignmentSequenceTarget target |
|
||||
nodeFrom = TIterableElementNode(target) and
|
||||
nodeTo.asCfgNode() = target and
|
||||
nodeTo.(CfgNode).getNode() = target and
|
||||
exists(int index | exists(target.getElement(index)) |
|
||||
c.(TupleElementContent).getIndex() = index
|
||||
)
|
||||
@@ -331,7 +331,7 @@ predicate iterableUnpackingElementReadStep(Node nodeFrom, Content c, Node nodeTo
|
||||
not exists(target.getAnElement().(StarredNode)) and
|
||||
starIndex = -1
|
||||
|
|
||||
nodeFrom.asCfgNode() = target and
|
||||
nodeFrom.(CfgNode).getNode() = target and
|
||||
element = target.getElement(index) and
|
||||
(
|
||||
if starIndex = -1 or index < starIndex
|
||||
|
||||
@@ -69,8 +69,8 @@ predicate matchSubjectFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
subject = match.getSubject() and
|
||||
target = match.getCase(_).(Case).getPattern()
|
||||
|
|
||||
nodeFrom.asExpr() = subject and
|
||||
nodeTo.asCfgNode().getNode() = target
|
||||
nodeFrom.(CfgNode).getNode().getNode() = subject and
|
||||
nodeTo.(CfgNode).getNode().getNode() = target
|
||||
)
|
||||
}
|
||||
|
||||
@@ -84,12 +84,13 @@ predicate matchAsFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
// That way, information can propagate from the interior pattern to the alias.
|
||||
//
|
||||
// the subject flows to the interior pattern
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = subject.getPattern()
|
||||
nodeFrom.(CfgNode).getNode().getNode() = subject and
|
||||
nodeTo.(CfgNode).getNode().getNode() = subject.getPattern()
|
||||
or
|
||||
// the interior pattern flows to the alias
|
||||
nodeFrom.asCfgNode().getNode() = subject.getPattern() and
|
||||
nodeTo.asVar().getDefinition().(PatternAliasDefinition).getDefiningNode().getNode() = alias
|
||||
nodeFrom.(CfgNode).getNode().getNode() = subject.getPattern() and
|
||||
nodeTo.(EssaNode).getVar().getDefinition().(PatternAliasDefinition).getDefiningNode().getNode() =
|
||||
alias
|
||||
)
|
||||
}
|
||||
|
||||
@@ -99,8 +100,8 @@ predicate matchAsFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
*/
|
||||
predicate matchOrFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchOrPattern subject, Pattern pattern | pattern = subject.getAPattern() |
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = pattern
|
||||
nodeFrom.(CfgNode).getNode().getNode() = subject and
|
||||
nodeTo.(CfgNode).getNode().getNode() = pattern
|
||||
)
|
||||
}
|
||||
|
||||
@@ -110,8 +111,8 @@ predicate matchOrFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
*/
|
||||
predicate matchLiteralFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchLiteralPattern pattern, Expr literal | literal = pattern.getLiteral() |
|
||||
nodeFrom.asExpr() = literal and
|
||||
nodeTo.asCfgNode().getNode() = pattern
|
||||
nodeFrom.(CfgNode).getNode().getNode() = literal and
|
||||
nodeTo.(CfgNode).getNode().getNode() = pattern
|
||||
)
|
||||
}
|
||||
|
||||
@@ -121,8 +122,14 @@ predicate matchLiteralFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
*/
|
||||
predicate matchCaptureFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchCapturePattern capture, Name var | capture.getVariable() = var |
|
||||
nodeFrom.asCfgNode().getNode() = capture and
|
||||
nodeTo.asVar().getDefinition().(PatternCaptureDefinition).getDefiningNode().getNode() = var
|
||||
nodeFrom.(CfgNode).getNode().getNode() = capture and
|
||||
nodeTo
|
||||
.(EssaNode)
|
||||
.getVar()
|
||||
.getDefinition()
|
||||
.(PatternCaptureDefinition)
|
||||
.getDefiningNode()
|
||||
.getNode() = var
|
||||
)
|
||||
}
|
||||
|
||||
@@ -132,8 +139,8 @@ predicate matchCaptureFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
*/
|
||||
predicate matchValueFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchValuePattern pattern, Expr value | value = pattern.getValue() |
|
||||
nodeFrom.asExpr() = value and
|
||||
nodeTo.asCfgNode().getNode() = pattern
|
||||
nodeFrom.(CfgNode).getNode().getNode() = value and
|
||||
nodeTo.(CfgNode).getNode().getNode() = pattern
|
||||
)
|
||||
}
|
||||
|
||||
@@ -145,8 +152,8 @@ predicate matchSequenceReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(MatchSequencePattern subject, int index, Pattern element |
|
||||
element = subject.getPattern(index)
|
||||
|
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = element and
|
||||
nodeFrom.(CfgNode).getNode().getNode() = subject and
|
||||
nodeTo.(CfgNode).getNode().getNode() = element and
|
||||
(
|
||||
// tuple content
|
||||
c.(TupleElementContent).getIndex() = index
|
||||
@@ -173,7 +180,7 @@ predicate matchStarReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(MatchSequencePattern subject, int index, MatchStarPattern star |
|
||||
star = subject.getPattern(index)
|
||||
|
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeFrom.(CfgNode).getNode().getNode() = subject and
|
||||
nodeTo = TStarPatternElementNode(star) and
|
||||
(
|
||||
// tuple content
|
||||
@@ -200,7 +207,7 @@ predicate matchStarReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
predicate matchStarStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
exists(MatchStarPattern star |
|
||||
nodeFrom = TStarPatternElementNode(star) and
|
||||
nodeTo.asCfgNode().getNode() = star.getTarget() and
|
||||
nodeTo.(CfgNode).getNode().getNode() = star.getTarget() and
|
||||
c instanceof ListElementContent
|
||||
)
|
||||
}
|
||||
@@ -218,8 +225,8 @@ predicate matchMappingReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
key = keyValue.getKey() and
|
||||
value = keyValue.getValue()
|
||||
|
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = value and
|
||||
nodeFrom.(CfgNode).getNode().getNode() = subject and
|
||||
nodeTo.(CfgNode).getNode().getNode() = value and
|
||||
c.(DictionaryElementContent).getKey() = key.getLiteral().(StrConst).getText()
|
||||
)
|
||||
}
|
||||
@@ -233,8 +240,8 @@ predicate matchMappingReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
*/
|
||||
predicate matchMappingFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(MatchMappingPattern subject, MatchDoubleStarPattern dstar | dstar = subject.getAMapping() |
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = dstar.getTarget()
|
||||
nodeFrom.(CfgNode).getNode().getNode() = subject and
|
||||
nodeTo.(CfgNode).getNode().getNode() = dstar.getTarget()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -251,7 +258,7 @@ predicate matchMappingClearStep(Node n, Content c) {
|
||||
key = keyValue.getKey() and
|
||||
dstar = subject.getAMapping()
|
||||
|
|
||||
n.asCfgNode().getNode() = dstar.getTarget() and
|
||||
n.(CfgNode).getNode().getNode() = dstar.getTarget() and
|
||||
c.(DictionaryElementContent).getKey() = key.getLiteral().(StrConst).getText()
|
||||
)
|
||||
}
|
||||
@@ -266,8 +273,8 @@ predicate matchClassReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||
attr = keyword.getAttribute() and
|
||||
value = keyword.getValue()
|
||||
|
|
||||
nodeFrom.asCfgNode().getNode() = subject and
|
||||
nodeTo.asCfgNode().getNode() = value and
|
||||
nodeFrom.(CfgNode).getNode().getNode() = subject and
|
||||
nodeTo.(CfgNode).getNode().getNode() = value and
|
||||
c.(AttributeContent).getAttribute() = attr.getId()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -55,7 +55,8 @@ predicate callStep(DataFlowPublic::ArgumentNode nodeFrom, DataFlowPrivate::Param
|
||||
/** Holds if `nodeFrom` steps to `nodeTo` by being returned from a call. */
|
||||
predicate returnStep(DataFlowPrivate::ReturnNode nodeFrom, Node nodeTo) {
|
||||
exists(DataFlowPrivate::DataFlowSourceCall call |
|
||||
nodeFrom.getEnclosingCallable() = call.getCallable() and nodeTo.asCfgNode() = call.getNode()
|
||||
nodeFrom.getEnclosingCallable() = call.getCallable() and
|
||||
nodeTo.(DataFlowPublic::CfgNode).getNode() = call.getNode()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user