Visitar URL original
Unified: Data flow through enum constructors and operators by asgerf · Pull Request #22751 · github/codeql · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
dcdf0a0
unified: Add test with flow through enums
asgerf Oct 5, 2026
7aae4bc
unified: Support flow through enum constructors
asgerf Oct 5, 2026
ce622db
unified: Model postfix "!" as a read step
asgerf Oct 5, 2026
a58747a
unified: Model more unary and cast operators
asgerf Oct 5, 2026
488f131
unified: Add basic flow through arrays
asgerf Oct 5, 2026
a0c937c
unified: Also treat "!" as a taint step and update test output
asgerf Oct 5, 2026
dca1b90
unified: Manually add one-argument version of Data.init(contentsOf:)
asgerf Oct 5, 2026
143aef9
unified: Add path-injection specific step through 'path'
asgerf Oct 5, 2026
7c4a2e8
unified: Dont show ExprPattern in path
asgerf Oct 5, 2026
61fc5fd
unified: Improve join order
asgerf Oct 7, 2026
6ab5435
unified: Record consistency errors
asgerf Oct 8, 2026
677f52e
unified: Add consistency exclusion, but record the miss in a test case
asgerf Oct 8, 2026
c811698
unified: Fix bug in test case
asgerf Oct 8, 2026
c413773
unified: Make the test case type-checkable
asgerf Oct 8, 2026
18f97f7
unified: Mention flattening behavior of 'try?'
asgerf Oct 8, 2026
f1aeecb
unified: Add test case for one-arg Data call
asgerf Oct 8, 2026
9211707
unified: Update test output after rebasing
asgerf Oct 8, 2026
303385e
unified: Fix typo
asgerf Oct 8, 2026
cfc8be4
unified: Remove empty DataFlowConsistency.expected
asgerf Oct 9, 2026
d04059b
unified: Factor out EnumCaseClass
asgerf Oct 9, 2026
f4d4777
unified: Use EnumCaseConstructor in TypeInference
asgerf Oct 9, 2026
e103940
unified: Elaborate QLDoc for enum cases
asgerf Oct 9, 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
Prev Previous commit
Next Next commit
unified: Add basic flow through arrays
Only array literals and for-in statements are handled
  • Loading branch information
asgerf committed Oct 8, 2026
commit 488f1319216cef0513c9f70969dd426a0d2d1a5b
11 changes: 10 additions & 1 deletion unified/ql/lib/codeql/unified/internal/dataflow/Content.qll
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ private import unified
private import AllDataFlow

private newtype TContent =
TArrayElement() or
TNamedMember(string name) {
name = any(Identifier id).getValue()
or
Expand All @@ -15,7 +16,13 @@ private newtype TContent =
class Content extends TContent {
string asNamedMember() { this = TNamedMember(result) }

string toString() { result = this.asNamedMember() }
predicate isArrayElement() { this = TArrayElement() }

string toString() {
result = this.asNamedMember()
or
this.isArrayElement() and result = "ArrayElement"
}

Location getLocation() { none() }
}
Expand All @@ -36,4 +43,6 @@ class ContentSet extends TContentSet {

module ContentSet {
ContentSet namedMember(string name) { result.asSingleton().asNamedMember() = name }

ContentSet arrayElement() { result.asSingleton().isArrayElement() }
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,18 @@ predicate step(Node node1, Step step, Node node2) {
node2.isIncomingValue(expr.getExpr())
)
or
exists(ArrayLiteral expr |
node1.isResultValue(expr.getAnElement()) and
step.store(ContentSet::arrayElement()) and
node2.isResultValue(expr)
)
or
exists(ForEachStmt stmt |
node1.isResultValue(stmt.getIterable()) and
step.readArrayElement() and
node2.isIncomingValue(stmt.getPattern())
)
or
none() // Temporarily disable compilation errors from unsatisfiable types
}

Expand Down
8 changes: 8 additions & 0 deletions unified/ql/lib/codeql/unified/internal/dataflow/Step.qll
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,21 @@ class Step extends TStep {
pragma[nomagic]
predicate readName(string name) { this.read(ContentSet::namedMember(name)) }

/** Holds if this represents a step reading an element from an array. */
pragma[nomagic]
predicate readArrayElement() { this.read(ContentSet::arrayElement()) }

/** Holds if this represents a step storing into `contents`. */
predicate store(ContentSet contents) { this = TStoreStep(contents) }

/** Holds if this represents a step storing into the named member `name`. */
pragma[nomagic]
predicate storeName(string name) { this.store(ContentSet::namedMember(name)) }

/** Holds if this represents a step storing a value into an array. */
pragma[nomagic]
predicate storeArrayElement() { this.store(ContentSet::arrayElement()) }

string toString() {
this.value() and result = "value"
or
Expand Down
15 changes: 15 additions & 0 deletions unified/ql/test/library-tests/dataflow/test.expected
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,12 @@ edges
| test.swift:221:12:221:12 | y | test.swift:222:14:222:14 | y | provenance | |
| test.swift:221:16:221:16 | x | test.swift:221:16:221:27 | TypeCastExpr [some.0] | provenance | |
| test.swift:221:16:221:27 | TypeCastExpr [some.0] | test.swift:221:8:221:12 | ... .some(...) [some.0] | provenance | |
| test.swift:227:9:227:9 | x [ArrayElement] | test.swift:228:20:228:20 | x [ArrayElement] | provenance | |
| test.swift:227:13:227:46 | ArrayLiteral [ArrayElement] | test.swift:227:9:227:9 | x [ArrayElement] | provenance | |
| test.swift:227:14:227:28 | source(...) | test.swift:227:13:227:46 | ArrayLiteral [ArrayElement] | provenance | |
| test.swift:227:31:227:45 | source(...) | test.swift:227:13:227:46 | ArrayLiteral [ArrayElement] | provenance | |
| test.swift:228:9:228:15 | element | test.swift:229:14:229:20 | element | provenance | |
| test.swift:228:20:228:20 | x [ArrayElement] | test.swift:228:9:228:15 | element | provenance | |
nodes
| calls.swift:7:19:7:19 | x | semmle.label | x |
| calls.swift:8:14:8:14 | x | semmle.label | x |
Expand Down Expand Up @@ -627,6 +633,13 @@ nodes
| test.swift:221:16:221:16 | x | semmle.label | x |
| test.swift:221:16:221:27 | TypeCastExpr [some.0] | semmle.label | TypeCastExpr [some.0] |
| test.swift:222:14:222:14 | y | semmle.label | y |
| test.swift:227:9:227:9 | x [ArrayElement] | semmle.label | x [ArrayElement] |
| test.swift:227:13:227:46 | ArrayLiteral [ArrayElement] | semmle.label | ArrayLiteral [ArrayElement] |
| test.swift:227:14:227:28 | source(...) | semmle.label | source(...) |
| test.swift:227:31:227:45 | source(...) | semmle.label | source(...) |
| test.swift:228:9:228:15 | element | semmle.label | element |
| test.swift:228:20:228:20 | x [ArrayElement] | semmle.label | x [ArrayElement] |
| test.swift:229:14:229:20 | element | semmle.label | element |
subpaths
| calls.swift:31:17:31:30 | source(...) | calls.swift:28:19:28:19 | x | calls.swift:29:16:29:24 | ... + ... | calls.swift:31:10:31:31 | target(...) |
| calls.swift:32:17:32:30 | source(...) | calls.swift:28:19:28:19 | x | calls.swift:29:16:29:24 | ... + ... | calls.swift:32:10:32:31 | target(...) |
Expand Down Expand Up @@ -723,3 +736,5 @@ testFailures
| test.swift:219:10:219:20 | TypeCastExpr | test.swift:218:13:218:27 | source(...) | test.swift:219:10:219:20 | TypeCastExpr | $@ | test.swift:218:13:218:27 | source(...) | source(...) |
| test.swift:220:10:220:21 | TypeCastExpr | test.swift:218:13:218:27 | source(...) | test.swift:220:10:220:21 | TypeCastExpr | $@ | test.swift:218:13:218:27 | source(...) | source(...) |
| test.swift:222:14:222:14 | y | test.swift:218:13:218:27 | source(...) | test.swift:222:14:222:14 | y | $@ | test.swift:218:13:218:27 | source(...) | source(...) |
| test.swift:229:14:229:20 | element | test.swift:227:14:227:28 | source(...) | test.swift:229:14:229:20 | element | $@ | test.swift:227:14:227:28 | source(...) | source(...) |
| test.swift:229:14:229:20 | element | test.swift:227:31:227:45 | source(...) | test.swift:229:14:229:20 | element | $@ | test.swift:227:31:227:45 | source(...) | source(...) |
8 changes: 8 additions & 0 deletions unified/ql/test/library-tests/dataflow/test.swift
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,11 @@ func t24() {
sink(y) // $ hasValueFlow=t24.1
}
}

func t25() {
let x = [source("t25.1"), source("t25.2")]
for element in x {
sink(element) // $ hasValueFlow=t25.1 hasValueFlow=t25.2
}

}