Skip to content

Commit 6cb69c9

Browse files
authored
Merge pull request #11514 from geoffw0/generics
Swift: Fix for MaD with generics
2 parents ef9b503 + 59e9d08 commit 6cb69c9

File tree

7 files changed

+211
-25
lines changed

7 files changed

+211
-25
lines changed

swift/ql/.generated.list

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,9 @@ ql/lib/codeql/swift/elements/decl/IfConfigDeclConstructor.qll ebd945f0a081421bd7
3434
ql/lib/codeql/swift/elements/decl/ImportDeclConstructor.qll f2f09df91784d7a6d348d67eaf3429780ac820d2d3a08f66e1922ea1d4c8c60d 4496865a26be2857a335cbc00b112beb78a319ff891d0c5d2ad41a4d299f0457
3535
ql/lib/codeql/swift/elements/decl/InfixOperatorDecl.qll ca3af3b403b9d456029cb4f4b94b610a93d2d70ea71a3d6c4532088ebc83bd0b 5dec87f0c43948f38e942b204583043eb4f7386caa80cec8bf2857a2fd933ed4
3636
ql/lib/codeql/swift/elements/decl/InfixOperatorDeclConstructor.qll ca6c5c477e35e2d6c45f8e7a08577c43e151d3e16085f1eae5c0a69081714b04 73543543dff1f9847f3299091979fdf3d105a84e2bcdb890ce5d72ea18bba6c8
37-
ql/lib/codeql/swift/elements/decl/IterableDeclContext.qll 7b27fe02dca453d5bdb5f10be07978d98308e466bad5585b3040ed9c1a817737 fed59974e47c3011d4bddefb959f5cacaa3b770ad5a6db15558334ef02ad04e9
3837
ql/lib/codeql/swift/elements/decl/MissingMemberDeclConstructor.qll 82738836fa49447262e184d781df955429c5e3697d39bf3689397d828f04ce65 8ef82ed7c4f641dc8b4d71cd83944582da539c34fb3d946c2377883abada8578
3938
ql/lib/codeql/swift/elements/decl/ModuleDecl.qll 0d39d88c926d5633f467ab7a1db0101e8d61250ee5e4847de862232f997de783 410311bf3ae1efac53d8fd6515c2fe69d9ab79902c1048780e87d478cd200e26
4039
ql/lib/codeql/swift/elements/decl/ModuleDeclConstructor.qll 9b18b6d3517fd0c524ac051fd5dea288e8f923ada00fe4cc809cbebce036f890 0efc90492417089b0982a9a6d60310faba7a1fce5c1749396e3a29b3aac75dc5
41-
ql/lib/codeql/swift/elements/decl/NominalTypeDecl.qll 0b101f879e48e000074971d6412183f6be98fe99512037967ee650ffd82ec7a3 9faf5bd4e51b47a75edb67e9115281ca5b20ab6c0d8f6882f043734495bb399f
4240
ql/lib/codeql/swift/elements/decl/OpaqueTypeDecl.qll 7c4a5fda798c9b44e481905f28e6c105ab3f8ab5567c2c336b24d27102fd7d66 e84e0dd1a3175ad29123def00e71efbd6f4526a12601fc027b0892930602046b
4341
ql/lib/codeql/swift/elements/decl/OpaqueTypeDeclConstructor.qll f707aab3627801e94c63aedcded21eab14d3617c35da5cf317692eeb39c84710 20888ae6e386ae31e3cb9ff78155cb408e781ef1e7b6d687c2705843bcac0340
4442
ql/lib/codeql/swift/elements/decl/ParamDeclConstructor.qll cfa0ba73a9727b8222efbf65845d6df0d01800646feaf7b407b8ffe21a6691d8 916ff2d3e96546eac6828e1b151d4b045ce5f7bcd5d7dbb074f82ecf126b0e09

swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -390,18 +390,6 @@ predicate matchesSignature(AbstractFunctionDecl func, string signature) {
390390
paramsString(func) = signature
391391
}
392392

393-
private NominalType getDeclType(IterableDeclContext decl) {
394-
result = decl.(ClassDecl).getType()
395-
or
396-
result = decl.(StructDecl).getType()
397-
or
398-
result = getDeclType(decl.(ExtensionDecl).getExtendedTypeDecl())
399-
or
400-
result = decl.(EnumDecl).getType()
401-
or
402-
result = decl.(ProtocolDecl).getType()
403-
}
404-
405393
/**
406394
* Gets the element in module `namespace` that satisfies the following properties:
407395
* 1. If the element is a member of a class-like type, then the class-like type has name `type`
@@ -430,32 +418,33 @@ private Element interpretElement0(
430418
)
431419
or
432420
// Member functions
433-
exists(NominalType nomType, IterableDeclContext decl, MethodDecl method |
421+
exists(NominalTypeDecl nomTypeDecl, IterableDeclContext decl, MethodDecl method |
434422
method.getName() = name and
435423
method = decl.getAMember() and
436-
nomType.getFullName() = type and
424+
nomTypeDecl.getFullName() = type and
437425
matchesSignature(method, signature) and
438426
result = method
439427
|
440428
subtypes = true and
441-
getDeclType(decl) = nomType.getADerivedType*()
429+
decl.getNominalTypeDecl() = nomTypeDecl.getADerivedTypeDecl*()
442430
or
443431
subtypes = false and
444-
getDeclType(decl) = nomType
432+
decl.getNominalTypeDecl() = nomTypeDecl
445433
)
446434
or
435+
// Fields
447436
signature = "" and
448-
exists(NominalType nomType, IterableDeclContext decl, FieldDecl field |
437+
exists(NominalTypeDecl nomTypeDecl, IterableDeclContext decl, FieldDecl field |
449438
field.getName() = name and
450439
field = decl.getAMember() and
451-
nomType.getFullName() = type and
440+
nomTypeDecl.getFullName() = type and
452441
result = field
453442
|
454443
subtypes = true and
455-
getDeclType(decl) = nomType.getADerivedType*()
444+
decl.getNominalTypeDecl() = nomTypeDecl.getADerivedTypeDecl*()
456445
or
457446
subtypes = false and
458-
getDeclType(decl) = nomType
447+
decl.getNominalTypeDecl() = nomTypeDecl
459448
)
460449
)
461450
}
Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
1-
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
21
private import codeql.swift.generated.decl.IterableDeclContext
2+
private import codeql.swift.elements.decl.NominalTypeDecl
3+
private import codeql.swift.elements.decl.ExtensionDecl
34

4-
class IterableDeclContext extends Generated::IterableDeclContext { }
5+
/**
6+
* A nominal type (class, struct, enum or protocol) or extension.
7+
*/
8+
class IterableDeclContext extends Generated::IterableDeclContext {
9+
/**
10+
* Gets the `NominalTypeDecl` corresponding to this `IterableDeclContext`
11+
* resolving an extension to the extended type declaration.
12+
*/
13+
NominalTypeDecl getNominalTypeDecl() {
14+
result = this.(NominalTypeDecl)
15+
or
16+
result = this.(ExtensionDecl).getExtendedTypeDecl()
17+
}
18+
}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
21
private import codeql.swift.generated.decl.NominalTypeDecl
32

3+
/**
4+
* A class, struct, enum or protocol.
5+
*/
46
class NominalTypeDecl extends Generated::NominalTypeDecl { }

swift/ql/test/library-tests/dataflow/flowsources/FlowSources.expected

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,43 @@
55
| customurlschemes.swift:48:9:48:28 | ...[...] | Remote URL in UIApplicationDelegate.application.launchOptions |
66
| data.swift:18:20:18:20 | call to init(contentsOf:options:) | external |
77
| data.swift:18:20:18:54 | call to init(contentsOf:options:) | external |
8+
| file://:0:0:0:0 | .source1 | external |
9+
| file://:0:0:0:0 | .source1 | external |
10+
| file://:0:0:0:0 | .source4 | external |
11+
| file://:0:0:0:0 | .source9 | external |
12+
| generics.swift:10:9:10:16 | .source1 | external |
13+
| generics.swift:11:9:11:16 | .source2 | external |
14+
| generics.swift:12:9:12:24 | call to source3() | external |
15+
| generics.swift:48:9:48:17 | .source1 | external |
16+
| generics.swift:49:9:49:17 | .source2 | external |
17+
| generics.swift:50:9:50:25 | call to source3() | external |
18+
| generics.swift:51:9:51:18 | .source1 | external |
19+
| generics.swift:52:9:52:18 | .source2 | external |
20+
| generics.swift:53:9:53:26 | call to source3() | external |
21+
| generics.swift:54:9:54:17 | .source1 | external |
22+
| generics.swift:55:9:55:17 | .source2 | external |
23+
| generics.swift:56:9:56:25 | call to source3() | external |
24+
| generics.swift:57:9:57:17 | .source4 | external |
25+
| generics.swift:58:9:58:17 | .source5 | external |
26+
| generics.swift:59:9:59:25 | call to source6() | external |
27+
| generics.swift:60:9:60:17 | .source7 | external |
28+
| generics.swift:61:9:61:25 | call to source8() | external |
29+
| generics.swift:62:9:62:18 | .source1 | external |
30+
| generics.swift:63:9:63:18 | .source2 | external |
31+
| generics.swift:64:9:64:26 | call to source3() | external |
32+
| generics.swift:65:9:65:18 | .source9 | external |
33+
| generics.swift:66:9:66:18 | .source10 | external |
34+
| generics.swift:67:9:67:27 | call to source11() | external |
35+
| generics.swift:68:9:68:18 | .source12 | external |
36+
| generics.swift:69:9:69:27 | call to source13() | external |
37+
| generics.swift:88:9:88:15 | .source1 | external |
38+
| generics.swift:89:9:89:15 | .source2 | external |
39+
| generics.swift:90:9:90:14 | .source1 | external |
40+
| generics.swift:91:9:91:14 | .source2 | external |
41+
| generics.swift:92:9:92:15 | .source1 | external |
42+
| generics.swift:93:9:93:15 | .source2 | external |
43+
| generics.swift:112:9:112:15 | .source1 | external |
44+
| generics.swift:113:9:113:15 | .source2 | external |
845
| nsdata.swift:18:17:18:17 | call to init(contentsOf:) | external |
946
| nsdata.swift:18:17:18:40 | call to init(contentsOf:) | external |
1047
| nsdata.swift:19:17:19:17 | call to init(contentsOf:options:) | external |
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,33 @@
11
import swift
22
import codeql.swift.dataflow.FlowSources
3+
import codeql.swift.dataflow.ExternalFlow
4+
5+
/**
6+
* A models-as-data class expressing custom flow sources for this test. These
7+
* cases ensure that MaD source definitions are able to successfully match a
8+
* range of class fields and member functions.
9+
*/
10+
class CustomTestSourcesCsv extends SourceModelCsv {
11+
override predicate row(string row) {
12+
row =
13+
[
14+
";MySimpleClass;true;source1;;;;remote", ";MySimpleClass;true;source2;;;;remote",
15+
";MySimpleClass;true;source3();;;ReturnValue;remote",
16+
// ---
17+
";MyGeneric;true;source1;;;;remote", ";MyGeneric;true;source2;;;;remote",
18+
";MyGeneric;true;source3();;;ReturnValue;remote", ";MyDerived;true;source4;;;;remote",
19+
";MyDerived;true;source5;;;;remote", ";MyDerived;true;source6();;;ReturnValue;remote",
20+
";MyDerived;true;source7;;;;remote", ";MyDerived;true;source8();;;ReturnValue;remote",
21+
";MyDerived2;true;source9;;;;remote", ";MyDerived2;true;source10;;;;remote",
22+
";MyDerived2;true;source11();;;ReturnValue;remote", ";MyDerived2;true;source12;;;;remote",
23+
";MyDerived2;true;source13();;;ReturnValue;remote",
24+
// ---
25+
";MyProtocol;true;source1;;;;remote", ";MyProtocol;true;source2;;;;remote",
26+
// ---
27+
";MyProtocol2;true;source1;;;;remote", ";MyProtocol2;true;source2;;;;remote",
28+
]
29+
}
30+
}
331

432
from RemoteFlowSource source
533
select source, concat(source.getSourceType(), ", ")
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
2+
class MySimpleClass
3+
{
4+
let source1: Int = 0
5+
var source2: Int { get { return 0 } }
6+
func source3() -> Int { return 0 }
7+
}
8+
9+
func useMySimpleClass(simple: MySimpleClass) {
10+
_ = simple.source1 // SOURCE
11+
_ = simple.source2 // SOURCE
12+
_ = simple.source3() // SOURCE
13+
}
14+
15+
// ---
16+
17+
class MyGeneric<T> {
18+
let source1: Int = 0
19+
var source2: T? { get { return nil } }
20+
func source3() -> Int { return 0 }
21+
}
22+
23+
class MyDerived<T> : MyGeneric<T> {
24+
let source4: Int = 0
25+
var source5: T? { get { return nil } }
26+
func source6() -> Int { return 0 }
27+
}
28+
29+
extension MyDerived
30+
{
31+
var source7: Int { get { return 0 } }
32+
func source8() -> Int { return 0 }
33+
}
34+
35+
class MyDerived2 : MyGeneric<Int> {
36+
let source9: Int = 0
37+
var source10: Int { get { return 0 } }
38+
func source11() -> Int { return 0 }
39+
}
40+
41+
extension MyDerived2
42+
{
43+
var source12: Int { get { return 0 } }
44+
func source13() -> Int { return 0 }
45+
}
46+
47+
func useDerived(generic: MyGeneric<Int>, generic2: MyGeneric<Any>, derived: MyDerived<Int>, derived2: MyDerived2) {
48+
_ = generic.source1 // SOURCE
49+
_ = generic.source2 // SOURCE
50+
_ = generic.source3() // SOURCE
51+
_ = generic2.source1 // SOURCE
52+
_ = generic2.source2 // SOURCE
53+
_ = generic2.source3() // SOURCE
54+
_ = derived.source1 // SOURCE
55+
_ = derived.source2 // SOURCE
56+
_ = derived.source3() // SOURCE
57+
_ = derived.source4 // SOURCE
58+
_ = derived.source5 // SOURCE
59+
_ = derived.source6() // SOURCE
60+
_ = derived.source7 // SOURCE
61+
_ = derived.source8() // SOURCE
62+
_ = derived2.source1 // SOURCE
63+
_ = derived2.source2 // SOURCE
64+
_ = derived2.source3() // SOURCE
65+
_ = derived2.source9 // SOURCE
66+
_ = derived2.source10 // SOURCE
67+
_ = derived2.source11() // SOURCE
68+
_ = derived2.source12 // SOURCE
69+
_ = derived2.source13() // SOURCE
70+
}
71+
72+
// ---
73+
74+
protocol MyProtocol {
75+
var source1: Int { get }
76+
var source2: Int { get }
77+
}
78+
79+
class MyImpl<T> : MyProtocol {
80+
var source1: Int { get { return 0 } }
81+
}
82+
83+
extension MyImpl {
84+
var source2: Int { get { return 0 } }
85+
}
86+
87+
func useProtocol(proto: MyProtocol, impl: MyImpl<Int>, impl2: MyImpl<Any>) {
88+
_ = proto.source1 // SOURCE
89+
_ = proto.source2 // SOURCE
90+
_ = impl.source1 // SOURCE
91+
_ = impl.source2 // SOURCE
92+
_ = impl2.source1 // SOURCE
93+
_ = impl2.source2 // SOURCE
94+
}
95+
96+
// ---
97+
98+
protocol MyProtocol2 {
99+
var source1: Int { get }
100+
var source2: Int { get }
101+
}
102+
103+
class MyImpl2<T> {
104+
var source1: Int { get { return 0 } }
105+
}
106+
107+
extension MyImpl2 : MyProtocol2 {
108+
var source2: Int { get { return 0 } }
109+
}
110+
111+
func useProtocol2(proto: MyProtocol2, impl: MyImpl2<Int>, impl2: MyImpl2<Any>) {
112+
_ = proto.source1 // SOURCE
113+
_ = proto.source2 // SOURCE
114+
_ = impl.source1 // SOURCE [NOT DETECTED]
115+
_ = impl.source2 // SOURCE [NOT DETECTED]
116+
_ = impl2.source1 // SOURCE [NOT DETECTED]
117+
_ = impl2.source2 // SOURCE [NOT DETECTED]
118+
}

0 commit comments

Comments
 (0)