Unified: Add flow summary support by asgerf · Pull Request #22809 · github/codeql · GitHub
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
2312383
unified: Minimal flow-summary test
asgerf Oct 12, 2026
beadc8f
unified: Move isReturnNode and isOutNode into predicate
asgerf Oct 12, 2026
9bacf06
unified: Explicitly bind the ReturnKind
asgerf Oct 15, 2026
5725c0c
unified: First implementation
asgerf Oct 12, 2026
1fdab4b
unified: More cases
asgerf Oct 12, 2026
a74615e
unified: Add debugSummarizedCallable.ql
asgerf Oct 12, 2026
48825a2
unified: Use EmptyLocation for summary elements
asgerf Oct 12, 2026
c979232
unified: Update test output
asgerf Oct 12, 2026
e37077b
unified: Update path injection output
asgerf Oct 12, 2026
92455b7
unified: Mark alerts that have moved
asgerf Oct 12, 2026
be1b295
unified: More tests
asgerf Oct 12, 2026
84f3ee8
unified: Regression test for names only mentioned in MaD
asgerf Oct 12, 2026
72e2f06
unified: Fix for members only appearing in MaD
asgerf Oct 12, 2026
dd61a2a
unified: Add callback tests
asgerf Oct 12, 2026
a8b89e7
unified: Add test with taint summary
asgerf Oct 12, 2026
3f6faa8
unified: Respect bypassContentSet in more places
asgerf Oct 19, 2026
bcbea15
unified: Add failing test for flow into 'inout' param
asgerf Oct 19, 2026
6af7b65
unified: Model flow through the 'inout' operator '&'
asgerf Oct 19, 2026
74c679f
unified: Model postfix "!" with exprStep
asgerf Oct 19, 2026
1e43ad4
unified: Exclude summary nodes from postWithInFlowExclude
asgerf Oct 19, 2026
a245a44
unified: Add test with flow through Argument[self]
asgerf Oct 19, 2026
98b4fb4
unified: Fix MaD for Argument[self]
asgerf Oct 19, 2026
81a0755
unified: Update path injection test output
asgerf Oct 19, 2026
dd97587
unified: Handle TupleElement
asgerf Oct 19, 2026
b4e903f
unified: Avoid double representatives for self
asgerf Oct 19, 2026
e3a6dda
unified: Add regression test for cast on LHS
asgerf Oct 20, 2026
17e0a9a
unified: Also use exprStep for type casts
asgerf Oct 20, 2026
80ff183
unified: Detect and fix an invalid access path
asgerf Oct 20, 2026
be58844
unified: Rename FlowSummaries -> FlowSummary.qll
asgerf Oct 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions unified/ql/consistency-queries/DataFlowConsistency.ql
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import DataFlowGraph
import DataFlowInstantiation
import DataFlowNode
import DataFlowPlugin
import FlowSummary
import LocalSsa
import ParameterPositions
import Step
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ private import codeql.unified.internal.typeinference.TypeInference as T

DataFlowCallable viableCallable(DataFlowCall c) {
result.asSourceCallable() = T::resolveCallTarget(c.asExplicitCall())
or
result.asSummarizedCallable().matchesCall(c.asExplicitCall())
}
9 changes: 9 additions & 0 deletions unified/ql/lib/codeql/unified/internal/dataflow/Content.qll
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
private import unified
private import AllDataFlow

/**
* Holds if a MaD access path token of form `name[arg]` exists.
*/
predicate isAccessPathTokenPresent(string name, string arg) {
arg = any(FlowSummaryOutput::Private::AccessPathToken tok).getAnArgument(name)
}

private newtype TContent =
TArrayElement() or
TNamedMember(string name) {
Expand All @@ -11,6 +18,8 @@ private newtype TContent =
name = [0 .. 20].toString()
or
name = getEnumCaseParameterFieldFromArgument(_, _)
or
isAccessPathTokenPresent("Member", name)
} or
TCapturedVariable(CaptureSsaInput::CapturedVariable v)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ private import codeql.unified.internal.ExprPositions
private newtype TDataFlowCall =
TExplicitCall(CallExpr call) {
not isInBindingContext(call, _) // ignore constructor patterns
} or
TSummaryCall(SummarizedCallable callable, SummaryNode callee) {
FlowSummaryOutput::summaryCallbackRange(callable, callee)
}

/**
Expand All @@ -17,15 +20,33 @@ class DataFlowCall extends TDataFlowCall {
/** Gets the `CallExpr` wrapped by this dataflow call, if any. */
CallExpr asExplicitCall() { this = TExplicitCall(result) }

/** Holds if this is a synthesized call to `callee` in `callable`. */
predicate isSummaryCall(SummarizedCallable callable, SummaryNode callee) {
this = TSummaryCall(callable, callee)
}

/** Gets a textual representation of this call. */
string toString() { result = this.asExplicitCall().toString() }
string toString() {
result = this.asExplicitCall().toString()
or
exists(SummarizedCallable callable, SummaryNode callee |
this.isSummaryCall(callable, callee) and
result = "[summary] call to " + callee.toString() + " in " + callable.toString()
)
}

/** Gets the location of this call, if any. */
Location getLocation() { result = this.asExplicitCall().getLocation() }
Location getLocation() {
result = this.asExplicitCall().getLocation()
or
this.isSummaryCall(_, _) and result instanceof EmptyLocation
}

/** Gets the callable containing this call. */
DataFlowCallable getEnclosingCallable() {
result.asSourceCallable() = this.asExplicitCall().getEnclosingCallable()
or
this.isSummaryCall(result.asSummarizedCallable(), _)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ private import AllDataFlow
private import codeql.unified.internal.ExprPositions

private newtype TDataFlowCallable =
TSourceCallable(Callable callable) { not isInTypeContext(callable) }
TSourceCallable(Callable callable) { not isInTypeContext(callable) } or
TSummarizedCallable(SummarizedCallable callable)

/**
* A callable entity: either a function-like entity in source code or
Expand All @@ -15,11 +16,21 @@ class DataFlowCallable extends TDataFlowCallable {
/** Gets the `Callable` wrapped by this dataflow callable, if any. */
Callable asSourceCallable() { this = TSourceCallable(result) }

/** Gets the `SummarizedCallable` wrapped by this dataflow callable, if any. */
SummarizedCallable asSummarizedCallable() { this = TSummarizedCallable(result) }

/** Gets a string representation of this call. */
string toString() { result = this.asSourceCallable().toString() }
string toString() {
result = this.asSourceCallable().toString() or
result = this.asSummarizedCallable().toString()
}

/** Gets the location of this call, if any. */
Location getLocation() { result = this.asSourceCallable().getLocation() }
Location getLocation() {
result = this.asSourceCallable().getLocation()
or
this instanceof TSummarizedCallable and result instanceof EmptyLocation
}
}

DataFlowCallable toDataFlowCallable(Callable callable) { result.asSourceCallable() = callable }
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@ private import codeql.unified.internal.LocalNameBinding
predicate step(BuilderNode node1, Step step, BuilderNode node2) {
any(DataFlowPlugin p).step(node1, step, node2)
or
exists(Expr expr1, Expr expr2, boolean mustFlow |
any(DataFlowPlugin p).exprStep(expr1, expr2, mustFlow)
|
node1.isResultValue(expr1) and
(if mustFlow = true then step.valueMustFlow() else step.value()) and
node2.isResultValue(expr2)
or
node1.isPostUpdate(expr2) and
step.value() and
node2.isPostUpdate(expr1)
)
or
exists(Callable callable |
node1.isReceiverParameter(callable) and
step.value() and
Expand Down
Loading
Loading