Skip to content

Commit ab58d4c

Browse files
authored
Merge pull request github#12415 from github/rdmarsh2/swift/constructor-flow
2 parents 50ff82f + d973236 commit ab58d4c

File tree

5 files changed

+118
-1
lines changed

5 files changed

+118
-1
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,19 @@ private module ReturnNodes {
400400
override ReturnKind getKind() { result instanceof NormalReturnKind }
401401
}
402402

403+
/**
404+
* A data-flow node that represents the `self` value in a constructor being
405+
* implicitly returned as the newly-constructed object
406+
*/
407+
class SelfReturnNode extends InoutReturnNodeImpl {
408+
SelfReturnNode() {
409+
exit.getScope() instanceof ConstructorDecl and
410+
param instanceof SelfParamDecl
411+
}
412+
413+
override ReturnKind getKind() { result instanceof NormalReturnKind }
414+
}
415+
403416
class InoutReturnNodeImpl extends ReturnNode, TInoutReturnNode, NodeImpl {
404417
ParamDecl param;
405418
ControlFlowNode exit;

swift/ql/test/library-tests/dataflow/dataflow/DataFlow.expected

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
edges
22
| file://:0:0:0:0 | [summary param] this in signum() : | file://:0:0:0:0 | [summary] to write: return (return) in signum() : |
33
| file://:0:0:0:0 | self [a, x] : | file://:0:0:0:0 | .a [x] : |
4+
| file://:0:0:0:0 | self [str] : | file://:0:0:0:0 | .str : |
45
| file://:0:0:0:0 | self [x] : | file://:0:0:0:0 | .x : |
56
| file://:0:0:0:0 | self [x] : | file://:0:0:0:0 | .x : |
67
| file://:0:0:0:0 | value : | file://:0:0:0:0 | [post] self [x] : |
@@ -155,15 +156,33 @@ edges
155156
| test.swift:472:20:472:20 | cx [x] : | test.swift:472:20:472:23 | .x : |
156157
| test.swift:472:20:472:23 | .x : | test.swift:473:15:473:15 | z1 |
157158
| test.swift:479:14:479:21 | call to source() : | test.swift:479:13:479:21 | call to +(_:) |
159+
| test.swift:488:9:488:9 | self [str] : | file://:0:0:0:0 | self [str] : |
160+
| test.swift:489:10:489:13 | s : | test.swift:490:13:490:13 | s : |
161+
| test.swift:490:7:490:7 | [post] self [str] : | test.swift:489:5:491:5 | self[return] [str] : |
162+
| test.swift:490:13:490:13 | s : | test.swift:490:7:490:7 | [post] self [str] : |
163+
| test.swift:495:17:498:5 | self[return] [str] : | test.swift:503:13:503:41 | call to Self.init(contentsOfFile:) [str] : |
164+
| test.swift:496:7:496:7 | [post] self [str] : | test.swift:495:17:498:5 | self[return] [str] : |
165+
| test.swift:496:7:496:7 | [post] self [str] : | test.swift:497:17:497:17 | self [str] : |
166+
| test.swift:496:20:496:28 | call to source3() : | test.swift:489:10:489:13 | s : |
167+
| test.swift:496:20:496:28 | call to source3() : | test.swift:496:7:496:7 | [post] self [str] : |
168+
| test.swift:497:17:497:17 | self [str] : | test.swift:497:17:497:17 | .str |
169+
| test.swift:502:13:502:33 | call to MyClass.init(s:) [str] : | test.swift:488:9:488:9 | self [str] : |
170+
| test.swift:502:13:502:33 | call to MyClass.init(s:) [str] : | test.swift:502:13:502:35 | .str |
171+
| test.swift:502:24:502:32 | call to source3() : | test.swift:489:10:489:13 | s : |
172+
| test.swift:502:24:502:32 | call to source3() : | test.swift:502:13:502:33 | call to MyClass.init(s:) [str] : |
173+
| test.swift:503:13:503:41 | call to Self.init(contentsOfFile:) [str] : | test.swift:488:9:488:9 | self [str] : |
174+
| test.swift:503:13:503:41 | call to Self.init(contentsOfFile:) [str] : | test.swift:503:13:503:43 | .str |
158175
nodes
159176
| file://:0:0:0:0 | .a [x] : | semmle.label | .a [x] : |
177+
| file://:0:0:0:0 | .str : | semmle.label | .str : |
160178
| file://:0:0:0:0 | .x : | semmle.label | .x : |
161179
| file://:0:0:0:0 | .x : | semmle.label | .x : |
162180
| file://:0:0:0:0 | [post] self [x] : | semmle.label | [post] self [x] : |
163181
| file://:0:0:0:0 | [post] self [x] : | semmle.label | [post] self [x] : |
164182
| file://:0:0:0:0 | [summary param] this in signum() : | semmle.label | [summary param] this in signum() : |
165183
| file://:0:0:0:0 | [summary] to write: return (return) in signum() : | semmle.label | [summary] to write: return (return) in signum() : |
166184
| file://:0:0:0:0 | self [a, x] : | semmle.label | self [a, x] : |
185+
| file://:0:0:0:0 | self [str] : | semmle.label | self [str] : |
167186
| file://:0:0:0:0 | self [x] : | semmle.label | self [x] : |
168187
| file://:0:0:0:0 | self [x] : | semmle.label | self [x] : |
169188
| file://:0:0:0:0 | value : | semmle.label | value : |
@@ -328,6 +347,21 @@ nodes
328347
| test.swift:479:13:479:21 | call to +(_:) | semmle.label | call to +(_:) |
329348
| test.swift:479:14:479:21 | call to source() : | semmle.label | call to source() : |
330349
| test.swift:480:14:480:21 | call to source() | semmle.label | call to source() |
350+
| test.swift:488:9:488:9 | self [str] : | semmle.label | self [str] : |
351+
| test.swift:489:5:491:5 | self[return] [str] : | semmle.label | self[return] [str] : |
352+
| test.swift:489:10:489:13 | s : | semmle.label | s : |
353+
| test.swift:490:7:490:7 | [post] self [str] : | semmle.label | [post] self [str] : |
354+
| test.swift:490:13:490:13 | s : | semmle.label | s : |
355+
| test.swift:495:17:498:5 | self[return] [str] : | semmle.label | self[return] [str] : |
356+
| test.swift:496:7:496:7 | [post] self [str] : | semmle.label | [post] self [str] : |
357+
| test.swift:496:20:496:28 | call to source3() : | semmle.label | call to source3() : |
358+
| test.swift:497:17:497:17 | .str | semmle.label | .str |
359+
| test.swift:497:17:497:17 | self [str] : | semmle.label | self [str] : |
360+
| test.swift:502:13:502:33 | call to MyClass.init(s:) [str] : | semmle.label | call to MyClass.init(s:) [str] : |
361+
| test.swift:502:13:502:35 | .str | semmle.label | .str |
362+
| test.swift:502:24:502:32 | call to source3() : | semmle.label | call to source3() : |
363+
| test.swift:503:13:503:41 | call to Self.init(contentsOfFile:) [str] : | semmle.label | call to Self.init(contentsOfFile:) [str] : |
364+
| test.swift:503:13:503:43 | .str | semmle.label | .str |
331365
subpaths
332366
| test.swift:75:21:75:22 | &... : | test.swift:65:16:65:28 | arg1 : | test.swift:65:1:70:1 | arg2[return] : | test.swift:75:31:75:32 | [post] &... : |
333367
| 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 ... : |
@@ -360,6 +394,10 @@ subpaths
360394
| test.swift:303:15:303:16 | ...! : | file://:0:0:0:0 | [summary param] this in signum() : | file://:0:0:0:0 | [summary] to write: return (return) in signum() : | test.swift:303:15:303:25 | call to signum() |
361395
| test.swift:468:12:468:12 | x : | test.swift:462:9:462:9 | value : | file://:0:0:0:0 | [post] self [x] : | test.swift:468:5:468:5 | [post] cx [x] : |
362396
| test.swift:472:20:472:20 | cx [x] : | test.swift:462:9:462:9 | self [x] : | file://:0:0:0:0 | .x : | test.swift:472:20:472:23 | .x : |
397+
| test.swift:496:20:496:28 | call to source3() : | test.swift:489:10:489:13 | s : | test.swift:490:7:490:7 | [post] self [str] : | test.swift:496:7:496:7 | [post] self [str] : |
398+
| test.swift:502:13:502:33 | call to MyClass.init(s:) [str] : | test.swift:488:9:488:9 | self [str] : | file://:0:0:0:0 | .str : | test.swift:502:13:502:35 | .str |
399+
| test.swift:502:24:502:32 | call to source3() : | test.swift:489:10:489:13 | s : | test.swift:489:5:491:5 | self[return] [str] : | test.swift:502:13:502:33 | call to MyClass.init(s:) [str] : |
400+
| test.swift:503:13:503:41 | call to Self.init(contentsOfFile:) [str] : | test.swift:488:9:488:9 | self [str] : | file://:0:0:0:0 | .str : | test.swift:503:13:503:43 | .str |
363401
#select
364402
| test.swift:7:15:7:15 | t1 | test.swift:6:19:6:26 | call to source() : | test.swift:7:15:7:15 | t1 | result |
365403
| test.swift:9:15:9:15 | t1 | test.swift:6:19:6:26 | call to source() : | test.swift:9:15:9:15 | t1 | result |
@@ -414,3 +452,6 @@ subpaths
414452
| test.swift:473:15:473:15 | z1 | test.swift:259:12:259:19 | call to source() : | test.swift:473:15:473:15 | z1 | result |
415453
| test.swift:479:13:479:21 | call to +(_:) | test.swift:479:14:479:21 | call to source() : | test.swift:479:13:479:21 | call to +(_:) | result |
416454
| test.swift:480:14:480:21 | call to source() | test.swift:480:14:480:21 | call to source() | test.swift:480:14:480:21 | call to source() | result |
455+
| test.swift:497:17:497:17 | .str | test.swift:496:20:496:28 | call to source3() : | test.swift:497:17:497:17 | .str | result |
456+
| test.swift:502:13:502:35 | .str | test.swift:502:24:502:32 | call to source3() : | test.swift:502:13:502:35 | .str | result |
457+
| test.swift:503:13:503:43 | .str | test.swift:496:20:496:28 | call to source3() : | test.swift:503:13:503:43 | .str | result |

swift/ql/test/library-tests/dataflow/dataflow/FlowConfig.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class TestConfiguration extends DataFlow::Configuration {
1515

1616
override predicate isSink(DataFlow::Node sink) {
1717
exists(CallExpr sinkCall |
18-
sinkCall.getStaticTarget().getName() = ["sink(arg:)", "sink(opt:)"] and
18+
sinkCall.getStaticTarget().getName() = ["sink(arg:)", "sink(opt:)", "sink(str:)"] and
1919
sinkCall.getAnArgument().getExpr() = sink.asExpr()
2020
)
2121
}

swift/ql/test/library-tests/dataflow/dataflow/LocalFlow.expected

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,3 +391,32 @@
391391
| test.swift:474:11:474:15 | SSA def(z2) | test.swift:475:15:475:15 | z2 |
392392
| test.swift:474:20:474:23 | .x | test.swift:474:11:474:15 | SSA def(z2) |
393393
| test.swift:479:14:479:21 | call to source() | test.swift:479:13:479:21 | call to +(_:) |
394+
| test.swift:487:7:487:7 | SSA def(self) | test.swift:487:7:487:7 | self[return] |
395+
| test.swift:487:7:487:7 | self | test.swift:487:7:487:7 | SSA def(self) |
396+
| test.swift:488:9:488:9 | self | test.swift:488:9:488:9 | SSA def(self) |
397+
| test.swift:488:9:488:9 | self | test.swift:488:9:488:9 | SSA def(self) |
398+
| test.swift:488:9:488:9 | self | test.swift:488:9:488:9 | SSA def(self) |
399+
| test.swift:488:9:488:9 | value | test.swift:488:9:488:9 | SSA def(value) |
400+
| test.swift:489:5:489:5 | SSA def(self) | test.swift:490:7:490:7 | self |
401+
| test.swift:489:5:489:5 | self | test.swift:489:5:489:5 | SSA def(self) |
402+
| test.swift:489:10:489:13 | SSA def(s) | test.swift:490:13:490:13 | s |
403+
| test.swift:489:10:489:13 | s | test.swift:489:10:489:13 | SSA def(s) |
404+
| test.swift:490:7:490:7 | [post] self | test.swift:489:5:491:5 | self[return] |
405+
| test.swift:490:7:490:7 | self | test.swift:489:5:491:5 | self[return] |
406+
| test.swift:495:17:495:17 | SSA def(self) | test.swift:496:7:496:7 | self |
407+
| test.swift:495:17:495:17 | self | test.swift:495:17:495:17 | SSA def(self) |
408+
| test.swift:496:7:496:7 | [post] self | test.swift:497:17:497:17 | self |
409+
| test.swift:496:7:496:7 | self | test.swift:497:17:497:17 | self |
410+
| test.swift:497:17:497:17 | [post] self | test.swift:495:17:498:5 | self[return] |
411+
| test.swift:497:17:497:17 | self | test.swift:495:17:498:5 | self[return] |
412+
| test.swift:501:21:501:27 | SSA def(path) | test.swift:503:37:503:37 | path |
413+
| test.swift:501:21:501:27 | path | test.swift:501:21:501:27 | SSA def(path) |
414+
| test.swift:506:7:506:7 | SSA def(self) | test.swift:506:7:506:7 | self[return] |
415+
| test.swift:506:7:506:7 | self | test.swift:506:7:506:7 | SSA def(self) |
416+
| test.swift:507:3:507:3 | SSA def(self) | test.swift:507:3:507:40 | self[return] |
417+
| test.swift:507:3:507:3 | self | test.swift:507:3:507:3 | SSA def(self) |
418+
| test.swift:507:27:507:38 | SSA def(n) | test.swift:507:3:507:40 | n[return] |
419+
| test.swift:507:31:507:38 | call to source() | test.swift:507:27:507:38 | SSA def(n) |
420+
| test.swift:513:7:513:7 | SSA def(n) | test.swift:514:36:514:36 | n |
421+
| test.swift:513:11:513:11 | 0 | test.swift:513:7:513:7 | SSA def(n) |
422+
| test.swift:514:36:514:36 | n | test.swift:514:35:514:36 | &... |

swift/ql/test/library-tests/dataflow/dataflow/test.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,3 +479,37 @@ func testIdentityArithmetic() {
479479
sink(arg: +source()) // $ flow=479
480480
sink(arg: (source())) // $ flow=480
481481
}
482+
483+
func sink(str: String) {}
484+
485+
func source3() -> String { return "" }
486+
487+
class MyClass {
488+
var str: String
489+
init(s: String) {
490+
str = s
491+
}
492+
}
493+
494+
extension MyClass {
495+
convenience init(contentsOfFile: String) {
496+
self.init(s: source3())
497+
sink(str: str) // $ flow=496
498+
}
499+
}
500+
501+
func extensionInits(path: String) {
502+
sink(str: MyClass(s: source3()).str) // $ flow=502
503+
sink(str: MyClass(contentsOfFile: path).str) // $ flow=496
504+
}
505+
506+
class InoutConstructorClass {
507+
init(_ n : inout Int) { n = source() }
508+
}
509+
510+
func sink(arg: InoutConstructorClass) {}
511+
512+
func inoutConstructor() {
513+
var n = 0
514+
sink(arg: InoutConstructorClass(&n))
515+
}

0 commit comments

Comments
 (0)