mirror of
https://github.com/github/codeql.git
synced 2026-05-05 13:45:19 +02:00
Merge pull request #14398 from rdmarsh2/rdmarsh2/swift/autoclosure-cfg
Swift: add CFG for normal autoclosures
This commit is contained in:
1
swift/ql/.generated.list
generated
1
swift/ql/.generated.list
generated
@@ -125,7 +125,6 @@ lib/codeql/swift/elements/expr/ErrorExpr.qll 8a68131297e574625a22fbbb28f3f09097e
|
||||
lib/codeql/swift/elements/expr/ErrorExprConstructor.qll dd2bec0e35121e0a65d47600100834963a7695c268e3832aad513e70b1b92a75 e85dcf686403511c5f72b25ae9cf62f77703575137c39610e61562efc988bbac
|
||||
lib/codeql/swift/elements/expr/ExistentialMetatypeToObjectExpr.qll 420d534f76e192e89f29c71a7282e0697d259c00a7edc3e168ca895b0dc4f1d1 c0b5811c8665f3324b04d40f5952a62e631ec4b3f00db8e9cc13cb5d60028178
|
||||
lib/codeql/swift/elements/expr/ExistentialMetatypeToObjectExprConstructor.qll 1a735425a59f8a2bd208a845e3b4fc961632c82db3b69d0b71a1bc2875090f3b 769b6a80a451c64cbf9ce09729b34493a59330d4ef54ab0d51d8ff81305b680f
|
||||
lib/codeql/swift/elements/expr/ExplicitClosureExpr.qll 77626fd66735b1954e6ec80a50a36ce94dd725110a5051ab4034600c8ce5ca6f 4e169380503b98d00efd9f38e549621c21971ed9e92dbce601fb46df2f44de78
|
||||
lib/codeql/swift/elements/expr/ExplicitClosureExprConstructor.qll 171d9f028bfb80754ddc917d0f6a24185d30643c6c2c80a8a5681dba16a4c48e 0e560df706726c7d45ea95532a9e4df00c03e860b840179f973bab8009c437ab
|
||||
lib/codeql/swift/elements/expr/FloatLiteralExprConstructor.qll 4dfb34d32e4022b55caadcfbe147e94ebe771395c59f137228213a51a744ba10 1eb78fcda9e0b70d1993e02408fb6032035991bf937c4267149ab9c7c6a99d3a
|
||||
lib/codeql/swift/elements/expr/ForceTryExprConstructor.qll 48cbc408bb34a50558d25aa092188e1ad0f68d83e98836e05072037f3d8b49af 62ce7b92410bf712ecd49d3eb7dd9b195b9157415713aaf59712542339f37e4c
|
||||
|
||||
1
swift/ql/.gitattributes
generated
vendored
1
swift/ql/.gitattributes
generated
vendored
@@ -127,7 +127,6 @@
|
||||
/lib/codeql/swift/elements/expr/ErrorExprConstructor.qll linguist-generated
|
||||
/lib/codeql/swift/elements/expr/ExistentialMetatypeToObjectExpr.qll linguist-generated
|
||||
/lib/codeql/swift/elements/expr/ExistentialMetatypeToObjectExprConstructor.qll linguist-generated
|
||||
/lib/codeql/swift/elements/expr/ExplicitClosureExpr.qll linguist-generated
|
||||
/lib/codeql/swift/elements/expr/ExplicitClosureExprConstructor.qll linguist-generated
|
||||
/lib/codeql/swift/elements/expr/FloatLiteralExprConstructor.qll linguist-generated
|
||||
/lib/codeql/swift/elements/expr/ForceTryExprConstructor.qll linguist-generated
|
||||
|
||||
5
swift/ql/lib/change-notes/2023-10-06-autoclosure-cfg.md
Normal file
5
swift/ql/lib/change-notes/2023-10-06-autoclosure-cfg.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
|
||||
* The contents of autoclosure function parameters are now included in the control flow graph and data flow libraries.
|
||||
@@ -4,7 +4,7 @@ cached
|
||||
newtype TControlFlowElement =
|
||||
TAstElement(AstNode n) or
|
||||
TFuncDeclElement(Function func) { func.hasBody() } or
|
||||
TClosureElement(ExplicitClosureExpr clos) or
|
||||
TClosureElement(ClosureExpr clos) { isNormalAutoClosureOrExplicitClosure(clos) } or
|
||||
TPropertyGetterElement(Decl accessor, Expr ref) { isPropertyGetterElement(accessor, ref) } or
|
||||
TPropertySetterElement(Accessor accessor, AssignExpr assign) {
|
||||
isPropertySetterElement(accessor, assign)
|
||||
@@ -41,6 +41,15 @@ predicate isPropertyGetterElement(PropertyGetterElement pge, Accessor accessor,
|
||||
pge = TPropertyGetterElement(accessor, ref)
|
||||
}
|
||||
|
||||
predicate isNormalAutoClosureOrExplicitClosure(ClosureExpr clos) {
|
||||
// short-circuiting operators have a `BinaryExpr` as the parent of the `AutoClosureExpr`,
|
||||
// so we exclude them by checking for a `CallExpr`.
|
||||
clos instanceof AutoClosureExpr and
|
||||
exists(CallExpr call | call.getAnArgument().getExpr() = clos)
|
||||
or
|
||||
clos instanceof ExplicitClosureExpr
|
||||
}
|
||||
|
||||
private predicate hasDirectToImplementationSemantics(Expr e) {
|
||||
e.(MemberRefExpr).hasDirectToImplementationSemantics()
|
||||
or
|
||||
@@ -194,14 +203,18 @@ class KeyPathElement extends ControlFlowElement, TKeyPathElement {
|
||||
override string toString() { result = expr.toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A control flow element representing a closure in its role as a control flow
|
||||
* scope.
|
||||
*/
|
||||
class ClosureElement extends ControlFlowElement, TClosureElement {
|
||||
ExplicitClosureExpr expr;
|
||||
ClosureExpr expr;
|
||||
|
||||
ClosureElement() { this = TClosureElement(expr) }
|
||||
|
||||
override Location getLocation() { result = expr.getLocation() }
|
||||
|
||||
ExplicitClosureExpr getAst() { result = expr }
|
||||
ClosureExpr getAst() { result = expr }
|
||||
|
||||
override string toString() { result = expr.toString() }
|
||||
}
|
||||
|
||||
@@ -67,10 +67,13 @@ module CfgScope {
|
||||
final override predicate exit(ControlFlowElement last, Completion c) { last(tree, last, c) }
|
||||
}
|
||||
|
||||
private class ClosureExprScope extends Range_ instanceof ExplicitClosureExpr {
|
||||
private class ClosureExprScope extends Range_ instanceof ClosureExpr {
|
||||
Exprs::ClosureExprTree tree;
|
||||
|
||||
ClosureExprScope() { tree.getAst() = this }
|
||||
ClosureExprScope() {
|
||||
isNormalAutoClosureOrExplicitClosure(this) and
|
||||
tree.getAst() = this
|
||||
}
|
||||
|
||||
final override predicate entry(ControlFlowElement first) { first(tree, first) }
|
||||
|
||||
@@ -1145,12 +1148,16 @@ module Exprs {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The control flow for an explicit closure or a normal autoclosure in its
|
||||
* role as a control flow scope.
|
||||
*/
|
||||
class ClosureExprTree extends StandardPreOrderTree, TClosureElement {
|
||||
ExplicitClosureExpr expr;
|
||||
ClosureExpr expr;
|
||||
|
||||
ClosureExprTree() { this = TClosureElement(expr) }
|
||||
|
||||
ExplicitClosureExpr getAst() { result = expr }
|
||||
ClosureExpr getAst() { result = expr }
|
||||
|
||||
final override ControlFlowElement getChildElement(int i) {
|
||||
result.asAstNode() = expr.getParam(i)
|
||||
|
||||
@@ -4,7 +4,8 @@ private import codeql.swift.elements.expr.Expr
|
||||
|
||||
/**
|
||||
* A Swift autoclosure expression, that is, a closure automatically generated
|
||||
* around an argument when the parameter has the `@autoclosure` attribute. For
|
||||
* around an argument when the parameter has the `@autoclosure` attribute or
|
||||
* for the right-hand operand of short-circuiting logical operations. For
|
||||
* example, there is an `AutoClosureExpr` around the value `0` in:
|
||||
* ```
|
||||
* func myFunction(_ expr: @autoclosure () -> Int) {
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
private import codeql.swift.generated.expr.ExplicitClosureExpr
|
||||
|
||||
/**
|
||||
* A Swift explicit closure expr, that is, a closure written using
|
||||
* `{ ... -> ... in ... }` syntax rather than automatically generated by the
|
||||
* compiler.
|
||||
*/
|
||||
class ExplicitClosureExpr extends Generated::ExplicitClosureExpr { }
|
||||
|
||||
@@ -3366,6 +3366,24 @@ cfg.swift:
|
||||
# 545| getElse(): [BraceStmt] { ... }
|
||||
# 546| getElement(0): [ReturnStmt] return ...
|
||||
# 546| getResult(): [IntegerLiteralExpr] 0
|
||||
# 550| [NamedFunction] usesAutoclosure(_:)
|
||||
# 550| InterfaceType = (@autoclosure () -> Int) -> Int
|
||||
# 550| getParam(0): [ParamDecl] expr
|
||||
# 550| Type = () -> Int
|
||||
# 550| getBody(): [BraceStmt] { ... }
|
||||
# 551| getElement(0): [ReturnStmt] return ...
|
||||
# 551| getResult(): [CallExpr] call to ...
|
||||
# 551| getFunction(): [DeclRefExpr] expr
|
||||
# 554| [NamedFunction] autoclosureTest()
|
||||
# 554| InterfaceType = () -> ()
|
||||
# 554| getBody(): [BraceStmt] { ... }
|
||||
# 555| getElement(0): [CallExpr] call to usesAutoclosure(_:)
|
||||
# 555| getFunction(): [DeclRefExpr] usesAutoclosure(_:)
|
||||
# 555| getArgument(0): [Argument] : { ... }
|
||||
# 555| getExpr(): [AutoClosureExpr] { ... }
|
||||
# 555| getBody(): [BraceStmt] { ... }
|
||||
# 555| getElement(0): [ReturnStmt] return ...
|
||||
# 555| getResult(): [IntegerLiteralExpr] 1
|
||||
declarations.swift:
|
||||
# 1| [StructDecl] Foo
|
||||
# 2| getMember(0): [PatternBindingDecl] var ... = ...
|
||||
|
||||
@@ -546,3 +546,11 @@ func testNilCoalescing2(x: Bool?) -> Int {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func usesAutoclosure(_ expr: @autoclosure () -> Int) -> Int {
|
||||
return expr()
|
||||
}
|
||||
|
||||
func autoclosureTest() {
|
||||
usesAutoclosure(1)
|
||||
}
|
||||
|
||||
@@ -6317,3 +6317,63 @@ cfg.swift:
|
||||
|
||||
# 546| 0
|
||||
#-----| -> return ...
|
||||
|
||||
# 550| enter usesAutoclosure(_:)
|
||||
#-----| -> usesAutoclosure(_:)
|
||||
|
||||
# 550| exit usesAutoclosure(_:)
|
||||
|
||||
# 550| exit usesAutoclosure(_:) (normal)
|
||||
#-----| -> exit usesAutoclosure(_:)
|
||||
|
||||
# 550| usesAutoclosure(_:)
|
||||
#-----| -> expr
|
||||
|
||||
# 550| expr
|
||||
#-----| -> expr
|
||||
|
||||
# 551| return ...
|
||||
#-----| return -> exit usesAutoclosure(_:) (normal)
|
||||
|
||||
# 551| expr
|
||||
#-----| -> call to ...
|
||||
|
||||
# 551| call to ...
|
||||
#-----| -> return ...
|
||||
|
||||
# 554| autoclosureTest()
|
||||
#-----| -> usesAutoclosure(_:)
|
||||
|
||||
# 554| enter autoclosureTest()
|
||||
#-----| -> autoclosureTest()
|
||||
|
||||
# 554| exit autoclosureTest()
|
||||
|
||||
# 554| exit autoclosureTest() (normal)
|
||||
#-----| -> exit autoclosureTest()
|
||||
|
||||
# 555| usesAutoclosure(_:)
|
||||
#-----| -> { ... }
|
||||
|
||||
# 555| call to usesAutoclosure(_:)
|
||||
#-----| -> exit autoclosureTest() (normal)
|
||||
|
||||
# 555| 1
|
||||
#-----| -> return ...
|
||||
|
||||
# 555| enter { ... }
|
||||
#-----| -> { ... }
|
||||
|
||||
# 555| exit { ... }
|
||||
|
||||
# 555| exit { ... } (normal)
|
||||
#-----| -> exit { ... }
|
||||
|
||||
# 555| return ...
|
||||
#-----| -> exit { ... } (normal)
|
||||
|
||||
# 555| { ... }
|
||||
#-----| -> 1
|
||||
|
||||
# 555| { ... }
|
||||
#-----| -> call to usesAutoclosure(_:)
|
||||
|
||||
@@ -546,3 +546,11 @@ func testNilCoalescing2(x: Bool?) -> Int {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func usesAutoclosure(_ expr: @autoclosure () -> Int) -> Int {
|
||||
return expr()
|
||||
}
|
||||
|
||||
func autoclosureTest() {
|
||||
usesAutoclosure(1)
|
||||
}
|
||||
|
||||
@@ -603,6 +603,7 @@ edges
|
||||
| test.swift:883:21:883:39 | call to makeIterator() [Collection element] | test.swift:884:15:884:15 | generator [Collection element] |
|
||||
| test.swift:884:15:884:15 | generator [Collection element] | test.swift:884:15:884:30 | call to next() [some:0] |
|
||||
| test.swift:884:15:884:30 | call to next() [some:0] | test.swift:884:15:884:31 | ...! |
|
||||
| test.swift:908:19:908:26 | call to source() | test.swift:904:13:904:18 | call to ... |
|
||||
nodes
|
||||
| file://:0:0:0:0 | .a [x] | semmle.label | .a [x] |
|
||||
| file://:0:0:0:0 | .s [x] | semmle.label | .s [x] |
|
||||
@@ -1251,6 +1252,8 @@ nodes
|
||||
| test.swift:884:15:884:15 | generator [Collection element] | semmle.label | generator [Collection element] |
|
||||
| test.swift:884:15:884:30 | call to next() [some:0] | semmle.label | call to next() [some:0] |
|
||||
| test.swift:884:15:884:31 | ...! | semmle.label | ...! |
|
||||
| test.swift:904:13:904:18 | call to ... | semmle.label | call to ... |
|
||||
| test.swift:908:19:908:26 | call to source() | semmle.label | call to source() |
|
||||
subpaths
|
||||
| test.swift:75:22:75:22 | x | test.swift:65:16:65:28 | arg1 | test.swift:65:1:70:1 | arg2[return] | test.swift:75:32:75:32 | [post] y |
|
||||
| test.swift:114:19:114:19 | arg | test.swift:109:9:109:14 | arg | test.swift:110:12:110:12 | arg | test.swift:114:12:114:22 | call to ... |
|
||||
@@ -1448,3 +1451,4 @@ subpaths
|
||||
| test.swift:867:15:867:38 | \\...[...] | test.swift:873:24:873:31 | call to source() | test.swift:867:15:867:38 | \\...[...] | result |
|
||||
| test.swift:880:19:880:19 | elem | test.swift:877:21:877:28 | call to source() | test.swift:880:19:880:19 | elem | result |
|
||||
| test.swift:884:15:884:31 | ...! | test.swift:877:21:877:28 | call to source() | test.swift:884:15:884:31 | ...! | result |
|
||||
| test.swift:904:13:904:18 | call to ... | test.swift:908:19:908:26 | call to source() | test.swift:904:13:904:18 | call to ... | result |
|
||||
|
||||
@@ -1145,3 +1145,5 @@
|
||||
| test.swift:898:24:898:24 | $i$generator | test.swift:898:24:898:24 | SSA def($i$generator) |
|
||||
| test.swift:898:24:898:24 | SSA def($i$generator) | test.swift:898:5:898:5 | $i$generator |
|
||||
| test.swift:898:24:898:24 | call to makeAsyncIterator() | test.swift:898:24:898:24 | $i$generator |
|
||||
| test.swift:903:22:903:49 | SSA def(expr) | test.swift:904:13:904:13 | expr |
|
||||
| test.swift:903:22:903:49 | expr | test.swift:903:22:903:49 | SSA def(expr) |
|
||||
|
||||
@@ -898,4 +898,12 @@ func testAsyncFor () async {
|
||||
for try await i in stream {
|
||||
sink(arg: i) // $ MISSING: flow=892
|
||||
}
|
||||
}
|
||||
|
||||
func usesAutoclosure(_ expr: @autoclosure () -> Int) {
|
||||
sink(arg: expr()) // $ flow=908
|
||||
}
|
||||
|
||||
func autoclosureTest() {
|
||||
usesAutoclosure(source())
|
||||
}
|
||||
Reference in New Issue
Block a user