Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dataflow: Support alert provenance #15501

Merged
merged 23 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
2925e45
Java/Dataflow: Propagate MaD-id/model-id to PathGraph.
aschackmull Jan 10, 2024
eafc007
Legacy dataflow: Sync.
aschackmull Jan 10, 2024
004bda1
C#: Add alert provenance plumbing.
aschackmull Feb 2, 2024
ba60399
Go: Add alert provenance plumbing.
aschackmull Feb 5, 2024
82e6fbb
Swift: Add alert provenance plumbing.
aschackmull Feb 5, 2024
6991f54
Ruby: Add alert provenance plumbing.
aschackmull Feb 6, 2024
f202661
C++: Add alert provenance plumbing.
aschackmull Feb 7, 2024
a8fc100
Python: Add alert provenance plumbing.
aschackmull Feb 7, 2024
44147b9
JS: Sync.
aschackmull Feb 7, 2024
fdfb4a1
JS: Adapt to shared ApiGraphModels.qll changes.
aschackmull Feb 7, 2024
c355737
C++: Update expected output.
aschackmull Apr 4, 2024
647f9ab
C#: Update some expected output (uninteresting).
aschackmull Apr 4, 2024
c3946a9
C#: Update expected output (interesting)
aschackmull Apr 5, 2024
20e91f9
Go: Update expected output (uninteresting).
aschackmull Apr 8, 2024
c2f5731
Java: Update expected output (uninteresting).
aschackmull Apr 8, 2024
f85ff9d
Java: Update expected output (interesting).
aschackmull Apr 8, 2024
bfcfeda
Python: Update expected output (uninteresting).
aschackmull Apr 8, 2024
cbcdf1f
Python: Update expected output (interesting).
aschackmull Apr 8, 2024
7cc8fd0
Ruby: Update expected output (uninteresting).
aschackmull Apr 8, 2024
2c43d0c
Ruby: Update expected output (interesting).
aschackmull Apr 8, 2024
b7ee559
Swift: Update expected output (interesting).
aschackmull Apr 8, 2024
31a8657
Dataflow: Add change note.
aschackmull Apr 9, 2024
b4e23d9
Dataflow: Address review comments
aschackmull Apr 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,10 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { no
/** Extra data-flow steps needed for lambda flow analysis. */
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() }

predicate knownSourceModel(Node source, string model) { none() }

predicate knownSinkModel(Node sink, string model) { none() }

/**
* 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.
Expand Down
121 changes: 62 additions & 59 deletions cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,7 @@ private module ThisFlow {
*/
cached
predicate localFlowStep(Node nodeFrom, Node nodeTo) {
simpleLocalFlowStep(nodeFrom, nodeTo)
simpleLocalFlowStep(nodeFrom, nodeTo, _)
or
// Field flow is not strictly a "step" but covers the whole function
// transitively. There's no way to get a step-like relation out of the global
Expand All @@ -530,64 +530,67 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) {
* This is the local flow predicate that's used as a building block in global
* data flow. It may have less flow than the `localFlowStep` predicate.
*/
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
// Expr -> Expr
exprToExprStep_nocfg(nodeFrom.asExpr(), nodeTo.asExpr())
or
// Assignment -> LValue post-update node
//
// This is used for assignments whose left-hand side is not a variable
// assignment or a storeStep but is still modeled by other means. It could be
// a call to `operator*` or `operator[]` where taint should flow to the
// post-update node of the qualifier.
exists(AssignExpr assign |
nodeFrom.asExpr() = assign and
nodeTo.(PostUpdateNode).getPreUpdateNode().asExpr() = assign.getLValue()
)
or
// Node -> FlowVar -> VariableAccess
exists(FlowVar var |
(
exprToVarStep(nodeFrom.asExpr(), var)
or
varSourceBaseCase(var, nodeFrom.asParameter())
or
varSourceBaseCase(var, nodeFrom.asUninitialized())
or
var.definedPartiallyAt(nodeFrom.asPartialDefinition())
) and
varToNodeStep(var, nodeTo)
)
or
// Expr -> DefinitionByReferenceNode
exprToDefinitionByReferenceStep(nodeFrom.asExpr(), nodeTo.asDefiningArgument())
or
// `this` -> adjacent-`this`
ThisFlow::adjacentThisRefs(nodeFrom, nodeTo)
or
// post-update-`this` -> following-`this`-ref
ThisFlow::adjacentThisRefs(nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo)
or
// In `f(&x->a)`, this step provides the flow from post-`&` to post-`x->a`,
// from which there is field flow to `x` via reverse read.
exists(PartialDefinition def, Expr inner, Expr outer |
def.definesExpressions(inner, outer) and
inner = nodeTo.(InnerPartialDefinitionNode).getPreUpdateNode().asExpr() and
outer = nodeFrom.(PartialDefinitionNode).getPreUpdateNode().asExpr()
)
or
// Reverse flow: data that flows from the post-update node of a reference
// returned by a function call, back into the qualifier of that function.
// This allows data to flow 'in' through references returned by a modeled
// function such as `operator[]`.
exists(DataFlowFunction f, Call call, FunctionInput inModel, FunctionOutput outModel |
call.getTarget() = f and
inModel.isReturnValueDeref() and
outModel.isQualifierObject() and
f.hasDataFlow(inModel, outModel) and
nodeFrom.(PostUpdateNode).getPreUpdateNode().asExpr() = call and
nodeTo.asDefiningArgument() = call.getQualifier()
)
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo, string model) {
(
// Expr -> Expr
exprToExprStep_nocfg(nodeFrom.asExpr(), nodeTo.asExpr())
or
// Assignment -> LValue post-update node
//
// This is used for assignments whose left-hand side is not a variable
// assignment or a storeStep but is still modeled by other means. It could be
// a call to `operator*` or `operator[]` where taint should flow to the
// post-update node of the qualifier.
exists(AssignExpr assign |
nodeFrom.asExpr() = assign and
nodeTo.(PostUpdateNode).getPreUpdateNode().asExpr() = assign.getLValue()
)
or
// Node -> FlowVar -> VariableAccess
exists(FlowVar var |
(
exprToVarStep(nodeFrom.asExpr(), var)
or
varSourceBaseCase(var, nodeFrom.asParameter())
or
varSourceBaseCase(var, nodeFrom.asUninitialized())
or
var.definedPartiallyAt(nodeFrom.asPartialDefinition())
) and
varToNodeStep(var, nodeTo)
)
or
// Expr -> DefinitionByReferenceNode
exprToDefinitionByReferenceStep(nodeFrom.asExpr(), nodeTo.asDefiningArgument())
or
// `this` -> adjacent-`this`
ThisFlow::adjacentThisRefs(nodeFrom, nodeTo)
or
// post-update-`this` -> following-`this`-ref
ThisFlow::adjacentThisRefs(nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo)
or
// In `f(&x->a)`, this step provides the flow from post-`&` to post-`x->a`,
// from which there is field flow to `x` via reverse read.
exists(PartialDefinition def, Expr inner, Expr outer |
def.definesExpressions(inner, outer) and
inner = nodeTo.(InnerPartialDefinitionNode).getPreUpdateNode().asExpr() and
outer = nodeFrom.(PartialDefinitionNode).getPreUpdateNode().asExpr()
)
or
// Reverse flow: data that flows from the post-update node of a reference
// returned by a function call, back into the qualifier of that function.
// This allows data to flow 'in' through references returned by a modeled
// function such as `operator[]`.
exists(DataFlowFunction f, Call call, FunctionInput inModel, FunctionOutput outModel |
call.getTarget() = f and
inModel.isReturnValueDeref() and
outModel.isQualifierObject() and
f.hasDataFlow(inModel, outModel) and
nodeFrom.(PostUpdateNode).getPreUpdateNode().asExpr() = call and
nodeTo.asDefiningArgument() = call.getQualifier()
)
) and
model = ""
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ predicate localTaintStep(DataFlow::Node src, DataFlow::Node sink) {
* Holds if the additional step from `src` to `sink` should be included in all
* global taint flow configurations.
*/
predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) {
localAdditionalTaintStep(src, sink)
predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink, string model) {
localAdditionalTaintStep(src, sink) and model = ""
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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, _)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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, _)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1020,6 +1020,10 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { no
/** Extra data-flow steps needed for lambda flow analysis. */
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() }

predicate knownSourceModel(Node source, string model) { none() }

predicate knownSinkModel(Node sink, string model) { none() }

/**
* 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.
Expand Down Expand Up @@ -1096,7 +1100,7 @@ private predicate localFlowStepWithSummaries(Node node1, Node node2) {
or
readStep(node1, _, node2)
or
DataFlowImplCommon::argumentValueFlowsThrough(node1, _, node2)
DataFlowImplCommon::argumentValueFlowsThrough(node1, _, node2, _)
}

/** Holds if `node` flows to a node that is used in a `SwitchInstruction`. */
Expand Down
Loading
Loading