mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge branch 'main' into mad
This commit is contained in:
@@ -489,9 +489,9 @@ private module Cached {
|
||||
* model.
|
||||
*/
|
||||
cached
|
||||
predicate sourceNode(Node node, string kind) {
|
||||
predicate sourceNode(Node node, string kind, string model) {
|
||||
exists(SourceSinkInterpretationInput::InterpretNode n |
|
||||
isSourceNode(n, kind) and n.asNode() = node
|
||||
isSourceNode(n, kind, model) and n.asNode() = node
|
||||
)
|
||||
}
|
||||
|
||||
@@ -500,57 +500,76 @@ private module Cached {
|
||||
* model.
|
||||
*/
|
||||
cached
|
||||
predicate sinkNode(Node node, string kind) {
|
||||
predicate sinkNode(Node node, string kind, string model) {
|
||||
exists(SourceSinkInterpretationInput::InterpretNode n |
|
||||
isSinkNode(n, kind) and n.asNode() = node
|
||||
isSinkNode(n, kind, model) and n.asNode() = node
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import Cached
|
||||
|
||||
/**
|
||||
* Holds if `node` is specified as a source with the given kind in a MaD flow
|
||||
* model.
|
||||
*/
|
||||
predicate sourceNode(Node node, string kind) { sourceNode(node, kind, _) }
|
||||
|
||||
/**
|
||||
* Holds if `node` is specified as a sink with the given kind in a MaD flow
|
||||
* model.
|
||||
*/
|
||||
predicate sinkNode(Node node, string kind) { sinkNode(node, kind, _) }
|
||||
|
||||
private predicate interpretSummary(
|
||||
Function f, string input, string output, string kind, string provenance
|
||||
Function f, string input, string output, string kind, string provenance, string model
|
||||
) {
|
||||
exists(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
||||
|
|
||||
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, provenance) and
|
||||
model = "" and // TODO: Insert MaD provenance from summaryModel
|
||||
f = interpretElement(namespace, type, subtypes, name, signature, ext)
|
||||
)
|
||||
}
|
||||
|
||||
// adapter class for converting Mad summaries to `SummarizedCallable`s
|
||||
private class SummarizedCallableAdapter extends SummarizedCallable {
|
||||
SummarizedCallableAdapter() { interpretSummary(this, _, _, _, _) }
|
||||
SummarizedCallableAdapter() { interpretSummary(this, _, _, _, _, _) }
|
||||
|
||||
private predicate relevantSummaryElementManual(string input, string output, string kind) {
|
||||
private predicate relevantSummaryElementManual(
|
||||
string input, string output, string kind, string model
|
||||
) {
|
||||
exists(Provenance provenance |
|
||||
interpretSummary(this, input, output, kind, provenance) and
|
||||
interpretSummary(this, input, output, kind, provenance, model) and
|
||||
provenance.isManual()
|
||||
)
|
||||
}
|
||||
|
||||
private predicate relevantSummaryElementGenerated(string input, string output, string kind) {
|
||||
private predicate relevantSummaryElementGenerated(
|
||||
string input, string output, string kind, string model
|
||||
) {
|
||||
exists(Provenance provenance |
|
||||
interpretSummary(this, input, output, kind, provenance) and
|
||||
interpretSummary(this, input, output, kind, provenance, model) and
|
||||
provenance.isGenerated()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
override predicate propagatesFlow(
|
||||
string input, string output, boolean preservesValue, string model
|
||||
) {
|
||||
exists(string kind |
|
||||
this.relevantSummaryElementManual(input, output, kind)
|
||||
this.relevantSummaryElementManual(input, output, kind, model)
|
||||
or
|
||||
not this.relevantSummaryElementManual(_, _, _) and
|
||||
this.relevantSummaryElementGenerated(input, output, kind)
|
||||
not this.relevantSummaryElementManual(_, _, _, _) and
|
||||
this.relevantSummaryElementGenerated(input, output, kind, model)
|
||||
|
|
||||
if kind = "value" then preservesValue = true else preservesValue = false
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasProvenance(Provenance provenance) {
|
||||
interpretSummary(this, _, _, _, provenance)
|
||||
interpretSummary(this, _, _, _, provenance, _)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -263,9 +263,10 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
|
||||
predicate isBarrierOut(Node node, FlowState state) { none() }
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, Node node2) {
|
||||
predicate isAdditionalFlowStep(Node node1, Node node2, string model) {
|
||||
singleConfiguration() and
|
||||
any(Configuration config).isAdditionalFlowStep(node1, node2)
|
||||
any(Configuration config).isAdditionalFlowStep(node1, node2) and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
|
||||
@@ -7,6 +7,7 @@ private import codeql.swift.dataflow.Ssa
|
||||
private import codeql.swift.controlflow.BasicBlocks
|
||||
private import codeql.swift.dataflow.FlowSummary as FlowSummary
|
||||
private import codeql.swift.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
|
||||
private import codeql.swift.dataflow.ExternalFlow
|
||||
private import codeql.swift.frameworks.StandardLibrary.PointerTypes
|
||||
private import codeql.swift.frameworks.StandardLibrary.Array
|
||||
private import codeql.swift.frameworks.StandardLibrary.Dictionary
|
||||
@@ -184,127 +185,130 @@ private module Cached {
|
||||
nodeTo = getParameterDefNode(nodeFrom.asParameter())
|
||||
}
|
||||
|
||||
private predicate localFlowStepCommon(Node nodeFrom, Node nodeTo) {
|
||||
exists(Ssa::Definition def |
|
||||
// Step from assignment RHS to def
|
||||
def.(Ssa::WriteDefinition).assigns(nodeFrom.getCfgNode()) and
|
||||
nodeTo.asDefinition() = def
|
||||
or
|
||||
// step from def to first read
|
||||
nodeFrom.asDefinition() = def and
|
||||
nodeTo.getCfgNode() = def.getAFirstRead() and
|
||||
(
|
||||
nodeTo instanceof InoutReturnNodeImpl
|
||||
implies
|
||||
nodeTo.(InoutReturnNodeImpl).getParameter() = def.getSourceVariable().asVarDecl()
|
||||
private predicate localFlowStepCommon(Node nodeFrom, Node nodeTo, string model) {
|
||||
(
|
||||
exists(Ssa::Definition def |
|
||||
// Step from assignment RHS to def
|
||||
def.(Ssa::WriteDefinition).assigns(nodeFrom.getCfgNode()) and
|
||||
nodeTo.asDefinition() = def
|
||||
or
|
||||
// step from def to first read
|
||||
nodeFrom.asDefinition() = def and
|
||||
nodeTo.getCfgNode() = def.getAFirstRead() and
|
||||
(
|
||||
nodeTo instanceof InoutReturnNodeImpl
|
||||
implies
|
||||
nodeTo.(InoutReturnNodeImpl).getParameter() = def.getSourceVariable().asVarDecl()
|
||||
)
|
||||
or
|
||||
// use-use flow
|
||||
localSsaFlowStepUseUse(def, nodeFrom, nodeTo)
|
||||
or
|
||||
localSsaFlowStepUseUse(def, nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo)
|
||||
or
|
||||
// step from previous read to Phi node
|
||||
localFlowSsaInput(nodeFrom, def, nodeTo.asDefinition())
|
||||
)
|
||||
or
|
||||
// use-use flow
|
||||
localSsaFlowStepUseUse(def, nodeFrom, nodeTo)
|
||||
localFlowSsaParamInput(nodeFrom, nodeTo)
|
||||
or
|
||||
localSsaFlowStepUseUse(def, nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo)
|
||||
// flow through `&` (inout argument)
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(InOutExpr).getSubExpr()
|
||||
or
|
||||
// step from previous read to Phi node
|
||||
localFlowSsaInput(nodeFrom, def, nodeTo.asDefinition())
|
||||
)
|
||||
or
|
||||
localFlowSsaParamInput(nodeFrom, nodeTo)
|
||||
or
|
||||
// flow through `&` (inout argument)
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(InOutExpr).getSubExpr()
|
||||
or
|
||||
// reverse flow through `&` (inout argument)
|
||||
nodeFrom.(PostUpdateNode).getPreUpdateNode().asExpr().(InOutExpr).getSubExpr() =
|
||||
nodeTo.(PostUpdateNode).getPreUpdateNode().asExpr()
|
||||
or
|
||||
// flow through `try!` and similar constructs
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(AnyTryExpr).getSubExpr()
|
||||
or
|
||||
// flow through `!`
|
||||
// note: there's a case in `readStep` that handles when the source is the
|
||||
// `OptionalSomeContentSet` within the RHS. This case is for when the
|
||||
// `Optional` itself is tainted (which it usually shouldn't be, but
|
||||
// retaining this case increases robustness of flow).
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(ForceValueExpr).getSubExpr()
|
||||
or
|
||||
// read of an optional .some member via `let x: T = y: T?` pattern matching
|
||||
// note: similar to `ForceValueExpr` this is ideally a content `readStep` but
|
||||
// in practice we sometimes have taint on the optional itself.
|
||||
nodeTo.asPattern() = nodeFrom.asPattern().(OptionalSomePattern).getSubPattern()
|
||||
or
|
||||
// flow through `?` and `?.`
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(BindOptionalExpr).getSubExpr()
|
||||
or
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(OptionalEvaluationExpr).getSubExpr()
|
||||
or
|
||||
// flow through unary `+` (which does nothing)
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(UnaryPlusExpr).getOperand()
|
||||
or
|
||||
// flow through varargs expansions (that wrap an `ArrayExpr` where varargs enter a call)
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(VarargExpansionExpr).getSubExpr()
|
||||
or
|
||||
// flow through nil-coalescing operator `??`
|
||||
exists(BinaryExpr nco |
|
||||
nco.getOperator().(FreeFunction).getName() = "??(_:_:)" and
|
||||
nodeTo.asExpr() = nco
|
||||
|
|
||||
// value argument
|
||||
nodeFrom.asExpr() = nco.getAnOperand()
|
||||
// reverse flow through `&` (inout argument)
|
||||
nodeFrom.(PostUpdateNode).getPreUpdateNode().asExpr().(InOutExpr).getSubExpr() =
|
||||
nodeTo.(PostUpdateNode).getPreUpdateNode().asExpr()
|
||||
or
|
||||
// unpack closure (the second argument is an `AutoClosureExpr` argument)
|
||||
nodeFrom.asExpr() = nco.getAnOperand().(AutoClosureExpr).getExpr()
|
||||
)
|
||||
or
|
||||
// flow through ternary operator `? :`
|
||||
exists(IfExpr ie |
|
||||
nodeTo.asExpr() = ie and
|
||||
nodeFrom.asExpr() = ie.getBranch(_)
|
||||
)
|
||||
or
|
||||
// flow through OpenExistentialExpr (compiler generated expression wrapper)
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(OpenExistentialExpr).getSubExpr()
|
||||
or
|
||||
// flow from Expr to Pattern
|
||||
exists(Expr e, Pattern p |
|
||||
nodeFrom.asExpr() = e and
|
||||
nodeTo.asPattern() = p and
|
||||
p.getImmediateMatchingExpr() = e
|
||||
)
|
||||
or
|
||||
// flow from Pattern to an identity-preserving sub-Pattern:
|
||||
nodeTo.asPattern() =
|
||||
[
|
||||
nodeFrom.asPattern().(IsPattern).getSubPattern(),
|
||||
nodeFrom.asPattern().(TypedPattern).getSubPattern()
|
||||
]
|
||||
or
|
||||
// Flow from the last component in a key path chain to
|
||||
// the return node for the key path.
|
||||
exists(KeyPathExpr keyPath |
|
||||
nodeFrom.(KeyPathComponentNodeImpl).getComponent() =
|
||||
keyPath.getComponent(keyPath.getNumberOfComponents() - 1) and
|
||||
nodeTo.(KeyPathReturnNodeImpl).getKeyPathExpr() = keyPath
|
||||
)
|
||||
or
|
||||
exists(KeyPathExpr keyPath |
|
||||
nodeTo.(KeyPathComponentPostUpdateNode).getComponent() =
|
||||
keyPath.getComponent(keyPath.getNumberOfComponents() - 1) and
|
||||
nodeFrom.(KeyPathReturnPostUpdateNode).getKeyPathExpr() = keyPath
|
||||
)
|
||||
or
|
||||
// Flow to the result of a keypath assignment
|
||||
exists(KeyPathApplicationExpr apply, AssignExpr assign |
|
||||
apply = assign.getDest() and
|
||||
nodeTo.asExpr() = apply and
|
||||
nodeFrom.asExpr() = assign.getSource()
|
||||
)
|
||||
// flow through `try!` and similar constructs
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(AnyTryExpr).getSubExpr()
|
||||
or
|
||||
// flow through `!`
|
||||
// note: there's a case in `readStep` that handles when the source is the
|
||||
// `OptionalSomeContentSet` within the RHS. This case is for when the
|
||||
// `Optional` itself is tainted (which it usually shouldn't be, but
|
||||
// retaining this case increases robustness of flow).
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(ForceValueExpr).getSubExpr()
|
||||
or
|
||||
// read of an optional .some member via `let x: T = y: T?` pattern matching
|
||||
// note: similar to `ForceValueExpr` this is ideally a content `readStep` but
|
||||
// in practice we sometimes have taint on the optional itself.
|
||||
nodeTo.asPattern() = nodeFrom.asPattern().(OptionalSomePattern).getSubPattern()
|
||||
or
|
||||
// flow through `?` and `?.`
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(BindOptionalExpr).getSubExpr()
|
||||
or
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(OptionalEvaluationExpr).getSubExpr()
|
||||
or
|
||||
// flow through unary `+` (which does nothing)
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(UnaryPlusExpr).getOperand()
|
||||
or
|
||||
// flow through varargs expansions (that wrap an `ArrayExpr` where varargs enter a call)
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(VarargExpansionExpr).getSubExpr()
|
||||
or
|
||||
// flow through nil-coalescing operator `??`
|
||||
exists(BinaryExpr nco |
|
||||
nco.getOperator().(FreeFunction).getName() = "??(_:_:)" and
|
||||
nodeTo.asExpr() = nco
|
||||
|
|
||||
// value argument
|
||||
nodeFrom.asExpr() = nco.getAnOperand()
|
||||
or
|
||||
// unpack closure (the second argument is an `AutoClosureExpr` argument)
|
||||
nodeFrom.asExpr() = nco.getAnOperand().(AutoClosureExpr).getExpr()
|
||||
)
|
||||
or
|
||||
// flow through ternary operator `? :`
|
||||
exists(IfExpr ie |
|
||||
nodeTo.asExpr() = ie and
|
||||
nodeFrom.asExpr() = ie.getBranch(_)
|
||||
)
|
||||
or
|
||||
// flow through OpenExistentialExpr (compiler generated expression wrapper)
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(OpenExistentialExpr).getSubExpr()
|
||||
or
|
||||
// flow from Expr to Pattern
|
||||
exists(Expr e, Pattern p |
|
||||
nodeFrom.asExpr() = e and
|
||||
nodeTo.asPattern() = p and
|
||||
p.getImmediateMatchingExpr() = e
|
||||
)
|
||||
or
|
||||
// flow from Pattern to an identity-preserving sub-Pattern:
|
||||
nodeTo.asPattern() =
|
||||
[
|
||||
nodeFrom.asPattern().(IsPattern).getSubPattern(),
|
||||
nodeFrom.asPattern().(TypedPattern).getSubPattern()
|
||||
]
|
||||
or
|
||||
// Flow from the last component in a key path chain to
|
||||
// the return node for the key path.
|
||||
exists(KeyPathExpr keyPath |
|
||||
nodeFrom.(KeyPathComponentNodeImpl).getComponent() =
|
||||
keyPath.getComponent(keyPath.getNumberOfComponents() - 1) and
|
||||
nodeTo.(KeyPathReturnNodeImpl).getKeyPathExpr() = keyPath
|
||||
)
|
||||
or
|
||||
exists(KeyPathExpr keyPath |
|
||||
nodeTo.(KeyPathComponentPostUpdateNode).getComponent() =
|
||||
keyPath.getComponent(keyPath.getNumberOfComponents() - 1) and
|
||||
nodeFrom.(KeyPathReturnPostUpdateNode).getKeyPathExpr() = keyPath
|
||||
)
|
||||
or
|
||||
// Flow to the result of a keypath assignment
|
||||
exists(KeyPathApplicationExpr apply, AssignExpr assign |
|
||||
apply = assign.getDest() and
|
||||
nodeTo.asExpr() = apply and
|
||||
nodeFrom.asExpr() = assign.getSource()
|
||||
)
|
||||
or
|
||||
// flow step according to the closure capture library
|
||||
captureValueStep(nodeFrom, nodeTo)
|
||||
) and
|
||||
model = ""
|
||||
or
|
||||
// flow through a flow summary (extension of `SummaryModelCsv`)
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
|
||||
nodeTo.(FlowSummaryNode).getSummaryNode(), true)
|
||||
or
|
||||
// flow step according to the closure capture library
|
||||
captureValueStep(nodeFrom, nodeTo)
|
||||
nodeTo.(FlowSummaryNode).getSummaryNode(), true, model)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -312,8 +316,8 @@ private module Cached {
|
||||
* data flow.
|
||||
*/
|
||||
cached
|
||||
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
localFlowStepCommon(nodeFrom, nodeTo)
|
||||
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo, string model) {
|
||||
localFlowStepCommon(nodeFrom, nodeTo, model)
|
||||
}
|
||||
|
||||
/** This is the local flow predicate that is exposed. */
|
||||
@@ -322,6 +326,7 @@ private module Cached {
|
||||
localFlowStepCommon(nodeFrom, nodeTo)
|
||||
or
|
||||
// models-as-data summarized flow
|
||||
localFlowStepCommon(nodeFrom, nodeTo, _) or
|
||||
FlowSummaryImpl::Private::Steps::summaryThroughStepValue(nodeFrom, nodeTo, _)
|
||||
}
|
||||
|
||||
@@ -1401,6 +1406,10 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
|
||||
/** Extra data-flow steps needed for lambda flow analysis. */
|
||||
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() }
|
||||
|
||||
predicate knownSourceModel(Node source, string model) { sourceNode(source, _, model) }
|
||||
|
||||
predicate knownSinkModel(Node sink, string model) { sinkNode(sink, _, model) }
|
||||
|
||||
/**
|
||||
* Holds if flow is allowed to pass from parameter `p` and back to itself as a
|
||||
* side-effect, resulting in a summary from `p` to itself.
|
||||
|
||||
@@ -120,12 +120,13 @@ module SourceSinkInterpretationInput implements
|
||||
* `output`, kind `kind`, and provenance `provenance`.
|
||||
*/
|
||||
predicate sourceElement(
|
||||
SourceOrSinkElement e, string output, string kind, Public::Provenance provenance
|
||||
SourceOrSinkElement e, string output, string kind, Public::Provenance provenance, string model
|
||||
) {
|
||||
exists(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
||||
|
|
||||
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance) and
|
||||
model = "" and // TODO: Insert MaD provenance from sourceModel
|
||||
e = interpretElement(namespace, type, subtypes, name, signature, ext)
|
||||
)
|
||||
}
|
||||
@@ -135,12 +136,13 @@ module SourceSinkInterpretationInput implements
|
||||
* `input`, kind `kind` and provenance `provenance`.
|
||||
*/
|
||||
predicate sinkElement(
|
||||
SourceOrSinkElement e, string input, string kind, Public::Provenance provenance
|
||||
SourceOrSinkElement e, string input, string kind, Public::Provenance provenance, string model
|
||||
) {
|
||||
exists(
|
||||
string package, string type, boolean subtypes, string name, string signature, string ext
|
||||
|
|
||||
sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance) and
|
||||
model = "" and // TODO: Insert MaD provenance from sinkModel
|
||||
e = interpretElement(package, type, subtypes, name, signature, ext)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -20,63 +20,66 @@ private module Cached {
|
||||
* in all global taint flow configurations.
|
||||
*/
|
||||
cached
|
||||
predicate defaultAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
// Flow through one argument of `appendLiteral` and `appendInterpolation` and to the second argument.
|
||||
// This is needed for string interpolation generated by the compiler. An interpolated string
|
||||
// like `"I am \(n) years old."` is represented as
|
||||
// ```
|
||||
// $interpolated = ""
|
||||
// appendLiteral(&$interpolated, "I am ")
|
||||
// appendInterpolation(&$interpolated, n)
|
||||
// appendLiteral(&$interpolated, " years old.")
|
||||
// ```
|
||||
exists(ApplyExpr apply, ExprCfgNode e |
|
||||
nodeFrom.asExpr() = [apply.getAnArgument().getExpr(), apply.getQualifier()] and
|
||||
apply.getStaticTarget().getName() = ["appendLiteral(_:)", "appendInterpolation(_:)"] and
|
||||
e.getExpr() = apply.getQualifier() and
|
||||
nodeTo.(PostUpdateNodeImpl).getPreUpdateNode().getCfgNode() = e
|
||||
)
|
||||
or
|
||||
// Flow from the computation of the interpolated string literal to the result of the interpolation.
|
||||
exists(InterpolatedStringLiteralExpr interpolated |
|
||||
nodeTo.asExpr() = interpolated and
|
||||
nodeFrom.asExpr() = interpolated.getAppendingExpr()
|
||||
)
|
||||
or
|
||||
// allow flow through arithmetic (this case includes string concatenation)
|
||||
nodeTo.asExpr().(ArithmeticOperation).getAnOperand() = nodeFrom.asExpr()
|
||||
or
|
||||
// allow flow through bitwise operations
|
||||
nodeTo.asExpr().(BitwiseOperation).getAnOperand() = nodeFrom.asExpr()
|
||||
or
|
||||
// allow flow through assignment operations (e.g. `+=`)
|
||||
exists(AssignOperation op |
|
||||
nodeFrom.asExpr() = op.getSource() and
|
||||
nodeTo.asExpr() = op.getDest()
|
||||
)
|
||||
or
|
||||
// flow through a subscript access
|
||||
exists(SubscriptExpr se |
|
||||
se.getBase() = nodeFrom.asExpr() and
|
||||
se = nodeTo.asExpr()
|
||||
)
|
||||
or
|
||||
// flow through autoclosure expressions (which turn value arguments into closure arguments);
|
||||
// if the value is tainted, it's helpful to consider the autoclosure itself to be tainted as
|
||||
// well for the purposes of matching sink models.
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(AutoClosureExpr).getExpr()
|
||||
or
|
||||
// flow through the read of a content that inherits taint
|
||||
exists(DataFlow::ContentSet f |
|
||||
readStep(nodeFrom, f, nodeTo) and
|
||||
f.getAReadContent() instanceof TaintInheritingContent
|
||||
)
|
||||
predicate defaultAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo, string model) {
|
||||
(
|
||||
// Flow through one argument of `appendLiteral` and `appendInterpolation` and to the second argument.
|
||||
// This is needed for string interpolation generated by the compiler. An interpolated string
|
||||
// like `"I am \(n) years old."` is represented as
|
||||
// ```
|
||||
// $interpolated = ""
|
||||
// appendLiteral(&$interpolated, "I am ")
|
||||
// appendInterpolation(&$interpolated, n)
|
||||
// appendLiteral(&$interpolated, " years old.")
|
||||
// ```
|
||||
exists(ApplyExpr apply, ExprCfgNode e |
|
||||
nodeFrom.asExpr() = [apply.getAnArgument().getExpr(), apply.getQualifier()] and
|
||||
apply.getStaticTarget().getName() = ["appendLiteral(_:)", "appendInterpolation(_:)"] and
|
||||
e.getExpr() = apply.getQualifier() and
|
||||
nodeTo.(PostUpdateNodeImpl).getPreUpdateNode().getCfgNode() = e
|
||||
)
|
||||
or
|
||||
// Flow from the computation of the interpolated string literal to the result of the interpolation.
|
||||
exists(InterpolatedStringLiteralExpr interpolated |
|
||||
nodeTo.asExpr() = interpolated and
|
||||
nodeFrom.asExpr() = interpolated.getAppendingExpr()
|
||||
)
|
||||
or
|
||||
// allow flow through arithmetic (this case includes string concatenation)
|
||||
nodeTo.asExpr().(ArithmeticOperation).getAnOperand() = nodeFrom.asExpr()
|
||||
or
|
||||
// allow flow through bitwise operations
|
||||
nodeTo.asExpr().(BitwiseOperation).getAnOperand() = nodeFrom.asExpr()
|
||||
or
|
||||
// allow flow through assignment operations (e.g. `+=`)
|
||||
exists(AssignOperation op |
|
||||
nodeFrom.asExpr() = op.getSource() and
|
||||
nodeTo.asExpr() = op.getDest()
|
||||
)
|
||||
or
|
||||
// flow through a subscript access
|
||||
exists(SubscriptExpr se |
|
||||
se.getBase() = nodeFrom.asExpr() and
|
||||
se = nodeTo.asExpr()
|
||||
)
|
||||
or
|
||||
// flow through autoclosure expressions (which turn value arguments into closure arguments);
|
||||
// if the value is tainted, it's helpful to consider the autoclosure itself to be tainted as
|
||||
// well for the purposes of matching sink models.
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(AutoClosureExpr).getExpr()
|
||||
or
|
||||
// flow through the read of a content that inherits taint
|
||||
exists(DataFlow::ContentSet f |
|
||||
readStep(nodeFrom, f, nodeTo) and
|
||||
f.getAReadContent() instanceof TaintInheritingContent
|
||||
)
|
||||
) and
|
||||
model = ""
|
||||
or
|
||||
// flow through a flow summary (extension of `SummaryModelCsv`)
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
|
||||
nodeTo.(FlowSummaryNode).getSummaryNode(), false)
|
||||
nodeTo.(FlowSummaryNode).getSummaryNode(), false, model)
|
||||
or
|
||||
any(AdditionalTaintStep a).step(nodeFrom, nodeTo)
|
||||
any(AdditionalTaintStep a).step(nodeFrom, nodeTo) and model = "AdditionalTaintStep"
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,7 +90,7 @@ private module Cached {
|
||||
predicate localTaintStepCached(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
DataFlow::localFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
defaultAdditionalTaintStep(nodeFrom, nodeTo)
|
||||
defaultAdditionalTaintStep(nodeFrom, nodeTo, _)
|
||||
or
|
||||
// Simple flow through library code is included in the exposed local
|
||||
// step relation, even though flow is technically inter-procedural
|
||||
|
||||
@@ -127,7 +127,7 @@ abstract deprecated class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
this.isAdditionalTaintStep(node1, node2) or
|
||||
defaultAdditionalTaintStep(node1, node2)
|
||||
defaultAdditionalTaintStep(node1, node2, _)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,14 +23,23 @@ edges
|
||||
| testURL.swift:73:52:73:67 | call to get_secret_key() | testURL.swift:73:18:73:67 | ... .+(_:_:) ... | provenance | |
|
||||
| testURL.swift:75:53:75:69 | call to get_cert_string() | testURL.swift:75:18:75:69 | ... .+(_:_:) ... | provenance | |
|
||||
| testURL.swift:96:51:96:51 | certificate | testURL.swift:96:18:96:18 | "..." | provenance | |
|
||||
| testURL.swift:104:16:104:57 | call to SecKeyCopyExternalRepresentation(_:_:) | testURL.swift:105:19:105:53 | call to String.init(data:encoding:) | provenance | |
|
||||
| testURL.swift:104:16:104:57 | call to SecKeyCopyExternalRepresentation(_:_:) | testURL.swift:105:19:105:53 | call to String.init(data:encoding:) | provenance | AdditionalTaintStep |
|
||||
| testURL.swift:104:16:104:57 | call to SecKeyCopyExternalRepresentation(_:_:) | testURL.swift:105:32:105:32 | data | provenance | |
|
||||
| testURL.swift:104:16:104:57 | call to SecKeyCopyExternalRepresentation(_:_:) | testURL.swift:106:20:106:20 | "..." | provenance | |
|
||||
| testURL.swift:104:16:104:57 | call to SecKeyCopyExternalRepresentation(_:_:) | testURL.swift:106:20:106:20 | "..." | provenance | AdditionalTaintStep |
|
||||
| testURL.swift:105:6:105:10 | let ...? [some:0] | testURL.swift:105:10:105:10 | string | provenance | |
|
||||
| testURL.swift:105:6:105:10 | let ...? [some:0] | testURL.swift:105:10:105:10 | string | provenance | |
|
||||
| testURL.swift:105:6:105:10 | let ...? [some:0] | testURL.swift:105:10:105:10 | string | provenance | |
|
||||
| testURL.swift:105:6:105:10 | let ...? [some:0] | testURL.swift:105:10:105:10 | string | provenance | |
|
||||
| testURL.swift:105:10:105:10 | string | testURL.swift:106:20:106:20 | "..." | provenance | |
|
||||
| testURL.swift:105:10:105:10 | string | testURL.swift:106:20:106:20 | "..." | provenance | |
|
||||
| testURL.swift:105:19:105:53 | call to String.init(data:encoding:) | testURL.swift:105:19:105:53 | call to String.init(data:encoding:) [some:0] | provenance | |
|
||||
| testURL.swift:105:19:105:53 | call to String.init(data:encoding:) | testURL.swift:105:19:105:53 | call to String.init(data:encoding:) [some:0] | provenance | |
|
||||
| testURL.swift:105:19:105:53 | call to String.init(data:encoding:) | testURL.swift:106:20:106:20 | "..." | provenance | |
|
||||
| testURL.swift:105:19:105:53 | call to String.init(data:encoding:) [some:0] | testURL.swift:105:6:105:10 | let ...? [some:0] | provenance | |
|
||||
| testURL.swift:105:19:105:53 | call to String.init(data:encoding:) [some:0] | testURL.swift:105:6:105:10 | let ...? [some:0] | provenance | |
|
||||
| testURL.swift:105:19:105:53 | call to String.init(data:encoding:) [some:0] | testURL.swift:105:6:105:10 | let ...? [some:0] | provenance | |
|
||||
| testURL.swift:105:19:105:53 | call to String.init(data:encoding:) [some:0] | testURL.swift:105:6:105:10 | let ...? [some:0] | provenance | |
|
||||
| testURL.swift:105:32:105:32 | data | testURL.swift:105:19:105:53 | call to String.init(data:encoding:) [some:0] | provenance | |
|
||||
| testURL.swift:105:32:105:32 | data | testURL.swift:105:19:105:53 | call to String.init(data:encoding:) [some:0] | provenance | |
|
||||
nodes
|
||||
| file://:0:0:0:0 | .value | semmle.label | .value |
|
||||
@@ -85,9 +94,12 @@ nodes
|
||||
| testURL.swift:96:51:96:51 | certificate | semmle.label | certificate |
|
||||
| testURL.swift:104:16:104:57 | call to SecKeyCopyExternalRepresentation(_:_:) | semmle.label | call to SecKeyCopyExternalRepresentation(_:_:) |
|
||||
| testURL.swift:105:6:105:10 | let ...? [some:0] | semmle.label | let ...? [some:0] |
|
||||
| testURL.swift:105:6:105:10 | let ...? [some:0] | semmle.label | let ...? [some:0] |
|
||||
| testURL.swift:105:10:105:10 | string | semmle.label | string |
|
||||
| testURL.swift:105:10:105:10 | string | semmle.label | string |
|
||||
| testURL.swift:105:19:105:53 | call to String.init(data:encoding:) | semmle.label | call to String.init(data:encoding:) |
|
||||
| testURL.swift:105:19:105:53 | call to String.init(data:encoding:) [some:0] | semmle.label | call to String.init(data:encoding:) [some:0] |
|
||||
| testURL.swift:105:19:105:53 | call to String.init(data:encoding:) [some:0] | semmle.label | call to String.init(data:encoding:) [some:0] |
|
||||
| testURL.swift:105:32:105:32 | data | semmle.label | data |
|
||||
| testURL.swift:106:20:106:20 | "..." | semmle.label | "..." |
|
||||
subpaths
|
||||
|
||||
44
swift/third_party/load.bzl
vendored
44
swift/third_party/load.bzl
vendored
@@ -40,7 +40,7 @@ def _get_toolchain_url(info):
|
||||
info.extension,
|
||||
)
|
||||
|
||||
def _toolchains(repository_name):
|
||||
def _toolchains():
|
||||
rules = {
|
||||
"tar.gz": http_archive,
|
||||
"pkg": _pkg_archive,
|
||||
@@ -51,7 +51,7 @@ def _toolchains(repository_name):
|
||||
name = "swift_toolchain_%s" % arch,
|
||||
url = _get_toolchain_url(info),
|
||||
sha256 = info.sha,
|
||||
build_file = _build(repository_name, "swift-toolchain-%s" % arch),
|
||||
build_file = _build % "swift-toolchain-%s" % arch,
|
||||
strip_prefix = "%s-%s" % (_swift_version, info.suffix),
|
||||
)
|
||||
|
||||
@@ -109,10 +109,9 @@ def _github_archive(*, name, repository, commit, build_file = None, sha256 = Non
|
||||
sha256 = sha256,
|
||||
)
|
||||
|
||||
def _build(repository_name, package):
|
||||
return "@%s//swift/third_party:BUILD.%s.bazel" % (repository_name, package)
|
||||
_build = "//swift/third_party:BUILD.%s.bazel"
|
||||
|
||||
def load_dependencies(module_ctx = None, repository_name = "codeql"):
|
||||
def load_dependencies(module_ctx):
|
||||
for repo_arch, arch in _swift_arch_map.items():
|
||||
sha256 = _swift_sha_map[repo_arch]
|
||||
|
||||
@@ -122,15 +121,15 @@ def load_dependencies(module_ctx = None, repository_name = "codeql"):
|
||||
_swift_prebuilt_version,
|
||||
repo_arch,
|
||||
),
|
||||
build_file = _build(repository_name, "swift-llvm-support"),
|
||||
build_file = _build % "swift-llvm-support",
|
||||
sha256 = sha256,
|
||||
)
|
||||
|
||||
_toolchains(repository_name)
|
||||
_toolchains()
|
||||
|
||||
_github_archive(
|
||||
name = "picosha2",
|
||||
build_file = _build(repository_name, "picosha2"),
|
||||
build_file = _build % "picosha2",
|
||||
repository = "okdshin/PicoSHA2",
|
||||
commit = "27fcf6979298949e8a462e16d09a0351c18fcaf2",
|
||||
sha256 = "d6647ca45a8b7bdaf027ecb68d041b22a899a0218b7206dee755c558a2725abb",
|
||||
@@ -138,34 +137,15 @@ def load_dependencies(module_ctx = None, repository_name = "codeql"):
|
||||
|
||||
_github_archive(
|
||||
name = "binlog",
|
||||
build_file = _build(repository_name, "binlog"),
|
||||
build_file = _build % "binlog",
|
||||
repository = "morganstanley/binlog",
|
||||
commit = "3fef8846f5ef98e64211e7982c2ead67e0b185a6",
|
||||
sha256 = "f5c61d90a6eff341bf91771f2f465be391fd85397023e1b391c17214f9cbd045",
|
||||
)
|
||||
|
||||
if module_ctx == None:
|
||||
# legacy workspace loading, remove when transition is complete
|
||||
_github_archive(
|
||||
name = "absl",
|
||||
repository = "abseil/abseil-cpp",
|
||||
commit = "d2c5297a3c3948de765100cb7e5cccca1210d23c",
|
||||
sha256 = "735a9efc673f30b3212bfd57f38d5deb152b543e35cd58b412d1363b15242049",
|
||||
)
|
||||
|
||||
_github_archive(
|
||||
name = "json",
|
||||
repository = "nlohmann/json",
|
||||
commit = "6af826d0bdb55e4b69e3ad817576745335f243ca",
|
||||
sha256 = "702bb0231a5e21c0374230fed86c8ae3d07ee50f34ffd420e7f8249854b7d85b",
|
||||
)
|
||||
|
||||
_github_archive(
|
||||
name = "fmt",
|
||||
repository = "fmtlib/fmt",
|
||||
build_file = _build(repository_name, "fmt"),
|
||||
commit = "a0b8a92e3d1532361c2f7feb63babc5c18d00ef2",
|
||||
sha256 = "ccf872fd4aa9ab3d030d62cffcb258ca27f021b2023a0244b2cf476f984be955",
|
||||
)
|
||||
return module_ctx.extension_metadata(
|
||||
root_module_direct_deps = "all",
|
||||
root_module_direct_dev_deps = [],
|
||||
)
|
||||
|
||||
swift_deps = module_extension(load_dependencies)
|
||||
|
||||
Reference in New Issue
Block a user