Skip to content

Commit eed42a4

Browse files
committed
Swift: Make a new scope for each KeyPath expression.
1 parent cd1800e commit eed42a4

File tree

5 files changed

+56
-16
lines changed

5 files changed

+56
-16
lines changed

swift/ql/lib/codeql/swift/controlflow/BasicBlocks.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ private module JoinBlockPredecessors {
207207
isPropertySetterElement(n, _, result)
208208
or
209209
isPropertyObserverElement(n, _, result)
210+
or
211+
result = n.(KeyPathElement).getAst()
212+
or
213+
result = n.(FuncDeclElement).getAst()
210214
}
211215

212216
int getId(JoinBlockPredecessor jbp) {

swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowElements.qll

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ newtype TControlFlowElement =
1010
} or
1111
TPropertyObserverElement(AccessorDecl observer, AssignExpr assign) {
1212
isPropertyObserverElement(observer, assign)
13-
}
13+
} or
14+
TKeyPathElement(KeyPathExpr expr)
1415

1516
predicate isLValue(Expr e) { any(AssignExpr assign).getDest() = e }
1617

@@ -171,4 +172,18 @@ class FuncDeclElement extends ControlFlowElement, TFuncDeclElement {
171172
override string toString() { result = func.toString() }
172173

173174
override Location getLocation() { result = func.getLocation() }
175+
176+
AbstractFunctionDecl getAst() { result = func }
177+
}
178+
179+
class KeyPathElement extends ControlFlowElement, TKeyPathElement {
180+
KeyPathExpr expr;
181+
182+
KeyPathElement() { this = TKeyPathElement(expr) }
183+
184+
override Location getLocation() { result = expr.getLocation() }
185+
186+
KeyPathExpr getAst() { result = expr }
187+
188+
override string toString() { result = expr.toString() }
174189
}

swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImpl.qll

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,23 @@ module CfgScope {
4747
}
4848

4949
private class BodyStmtCallableScope extends Range_ instanceof AbstractFunctionDecl {
50-
final override predicate entry(ControlFlowElement first) {
51-
exists(Decls::FuncDeclTree tree |
52-
tree.getAst() = this and
53-
first = tree
54-
)
55-
}
50+
Decls::FuncDeclTree tree;
5651

57-
final override predicate exit(ControlFlowElement last, Completion c) {
58-
exists(Decls::FuncDeclTree tree |
59-
tree.getAst() = this and
60-
tree.last(last, c)
61-
)
62-
}
52+
BodyStmtCallableScope() { tree.getAst() = this }
53+
54+
final override predicate entry(ControlFlowElement first) { first(tree, first) }
55+
56+
final override predicate exit(ControlFlowElement last, Completion c) { last(tree, last, c) }
57+
}
58+
59+
private class KeyPathScope extends Range_ instanceof KeyPathExpr {
60+
AstControlFlowTree tree;
61+
62+
KeyPathScope() { tree.getAst() = this.getParsedRoot().getFullyConverted() }
63+
64+
final override predicate entry(ControlFlowElement first) { first(tree, first) }
65+
66+
final override predicate exit(ControlFlowElement last, Completion c) { last(tree, last, c) }
6367
}
6468
}
6569

@@ -1062,6 +1066,20 @@ module Exprs {
10621066
}
10631067
}
10641068

1069+
class KeyPathTree extends AstLeafTree {
1070+
override KeyPathExpr ast;
1071+
}
1072+
1073+
class KeyPathApplicationTree extends AstStandardPostOrderTree {
1074+
override KeyPathApplicationExpr ast;
1075+
1076+
final override ControlFlowElement getChildElement(int i) {
1077+
i = 0 and result.asAstNode() = ast.getBase().getFullyConverted()
1078+
or
1079+
i = 1 and result.asAstNode() = ast.getKeyPath().getFullyConverted()
1080+
}
1081+
}
1082+
10651083
private class InOutTree extends AstStandardPostOrderTree {
10661084
override InOutExpr ast;
10671085

@@ -1586,7 +1604,9 @@ private module Cached {
15861604
result = scopeOfAst(n.asAstNode()) or
15871605
result = scopeOfAst(n.(PropertyGetterElement).getRef()) or
15881606
result = scopeOfAst(n.(PropertySetterElement).getAssignExpr()) or
1589-
result = scopeOfAst(n.(PropertyObserverElement).getAssignExpr())
1607+
result = scopeOfAst(n.(PropertyObserverElement).getAssignExpr()) or
1608+
result = n.(FuncDeclElement).getAst() or
1609+
result = n.(KeyPathElement).getAst()
15901610
}
15911611

15921612
cached

swift/ql/lib/codeql/swift/controlflow/internal/Scope.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
private import swift
22

33
module CallableBase {
4-
class TypeRange = @abstract_function_decl;
4+
class TypeRange = @abstract_function_decl or @key_path_expr;
55

66
class Range extends Scope::Range, TypeRange { }
77
}

swift/ql/lib/codeql/swift/dataflow/internal/DataFlowDispatch.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
private import swift
22
private import DataFlowPrivate
33
private import DataFlowPublic
4+
private import codeql.swift.controlflow.ControlFlowGraph
45

56
newtype TReturnKind = TNormalReturnKind()
67

@@ -53,7 +54,7 @@ class DataFlowCall extends ExprNode {
5354
cached
5455
private module Cached {
5556
cached
56-
newtype TDataFlowCallable = TDataFlowFunc(FuncDecl func)
57+
newtype TDataFlowCallable = TDataFlowFunc(CfgScope scope)
5758

5859
/** Gets a viable run-time target for the call `call`. */
5960
cached

0 commit comments

Comments
 (0)