Skip to content

Commit ab6e8b9

Browse files
authored
Merge pull request github#14252 from geoffw0/protocol3
Swift: Improve getABaseType implementions
2 parents 2c9433c + fef5a49 commit ab6e8b9

File tree

16 files changed

+154
-86
lines changed

16 files changed

+154
-86
lines changed

swift/ql/.generated.list

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

swift/ql/.gitattributes

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
category: majorAnalysis
3+
---
4+
5+
* The predicates `getABaseType`, `getABaseTypeDecl`, `getADerivedType` and `getADerivedTypeDecl` on `Type` and `TypeDecl` now behave more usefully and consistently. They now explore through type aliases used in base class declarations, and include protocols added in extensions.
6+
7+
To examine base class declarations at a low level without these enhancements, use `TypeDecl.getInheritedType`.
8+
9+
`Type.getABaseType` (only) previously resolved a type alias it was called directly on. This behaviour no longer exists. To find any base type of a type that could be an alias, the construct `Type.getUnderlyingType().getABaseType*()` is recommended.

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

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -417,14 +417,6 @@ private Element interpretElement0(
417417
subtypes = true and
418418
declWithMethod.asNominalTypeDecl() = namedTypeDecl.getADerivedTypeDecl*()
419419
or
420-
// member declared in a type that's extended with a protocol that is the named type
421-
exists(ExtensionDecl e |
422-
e.getExtendedTypeDecl().getADerivedTypeDecl*() = declWithMethod.asNominalTypeDecl()
423-
|
424-
subtypes = true and
425-
e.getAProtocol() = namedTypeDecl.getADerivedTypeDecl*()
426-
)
427-
or
428420
// member declared directly in the named type (or an extension of it)
429421
subtypes = false and
430422
declWithMethod.asNominalTypeDecl() = namedTypeDecl
@@ -442,14 +434,6 @@ private Element interpretElement0(
442434
subtypes = true and
443435
declWithField.asNominalTypeDecl() = namedTypeDecl.getADerivedTypeDecl*()
444436
or
445-
// field declared in a type that's extended with a protocol that is the named type
446-
exists(ExtensionDecl e |
447-
e.getExtendedTypeDecl().getADerivedTypeDecl*() = declWithField.asNominalTypeDecl()
448-
|
449-
subtypes = true and
450-
e.getAProtocol() = namedTypeDecl.getADerivedTypeDecl*()
451-
)
452-
or
453437
// field declared directly in the named type (or an extension of it)
454438
subtypes = false and
455439
declWithField.asNominalTypeDecl() = namedTypeDecl

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet cs)
3131
// So when the node is a `PostUpdateNode` we allow any sequence of implicit read steps of an appropriate
3232
// type to make sure we arrive at the sink with an empty access path.
3333
exists(NominalTypeDecl d, Decl cx |
34-
node.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr().getType() =
34+
node.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr().getType().getUnderlyingType() =
3535
d.getType().getABaseType*() and
3636
cx.asNominalTypeDecl() = d and
3737
cs.getAReadContent().(DataFlow::Content::FieldContent).getField() = cx.getAMember()
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
21
private import codeql.swift.generated.decl.TypeAliasDecl
32

3+
/**
4+
* A declaration of a type alias to another type. For example:
5+
* ```
6+
* typealias MyInt = Int
7+
* ```
8+
*/
49
class TypeAliasDecl extends Generated::TypeAliasDecl { }

swift/ql/lib/codeql/swift/elements/decl/TypeDecl.qll

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,24 @@ class TypeDecl extends Generated::TypeDecl {
3535
deprecated Type getBaseType(int index) { result = this.getInheritedType(index) }
3636

3737
/**
38-
* Gets any of the base types of this type declaration.
38+
* Gets any of the base types of this type declaration. Expands protocols added in
39+
* extensions and expands type aliases. For example in the following code, `B` has
40+
* base type `A`:
41+
* ```
42+
* typealias A_alias = A
43+
*
44+
* class B : A_alias {}
45+
* ```
3946
*/
4047
Type getABaseType() {
41-
// TODO generalize this to resolve `TypeAliasDecl`s and consider bases added by extensions
42-
result = this.getAnInheritedType()
48+
// direct base type
49+
result = this.getAnInheritedType().getUnderlyingType()
50+
or
51+
// protocol added in an extension of the type
52+
exists(ExtensionDecl ed |
53+
ed.getExtendedTypeDecl() = this and
54+
ed.getAProtocol().getType() = result
55+
)
4356
}
4457

4558
/**
@@ -51,7 +64,14 @@ class TypeDecl extends Generated::TypeDecl {
5164
}
5265

5366
/**
54-
* Gets the declaration of any of the base types of this type declaration.
67+
* Gets the declaration of any of the base types of this type declaration. Expands
68+
* protocols added in extensions and expands type aliases. For example in the following
69+
* code, `B` has base type `A`.
70+
* ```
71+
* typealias A_alias = A
72+
*
73+
* class B : A_alias {}
74+
* ```
5575
*/
5676
TypeDecl getABaseTypeDecl() { result = this.getABaseType().(AnyGenericType).getDeclaration() }
5777

@@ -63,7 +83,14 @@ class TypeDecl extends Generated::TypeDecl {
6383
deprecated TypeDecl getDerivedTypeDecl(int i) { result.getBaseTypeDecl(i) = this }
6484

6585
/**
66-
* Gets the declaration of any type derived from this type declaration.
86+
* Gets the declaration of any type derived from this type declaration. Expands protocols
87+
* added in extensions and expands type aliases. For example in the following code, `B`
88+
* is derived from `A`.
89+
* ```
90+
* typealias A_alias = A
91+
*
92+
* class B : A_alias {}
93+
* ```
6794
*/
6895
TypeDecl getADerivedTypeDecl() { result.getABaseTypeDecl() = this }
6996

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
private import codeql.swift.generated.type.NominalType
2-
private import codeql.swift.elements.decl.NominalTypeDecl
3-
private import codeql.swift.elements.type.Type
42

5-
class NominalType extends Generated::NominalType {
6-
override Type getABaseType() { result = this.getDeclaration().(NominalTypeDecl).getABaseType() }
7-
8-
NominalType getADerivedType() { result.getABaseType() = this }
9-
}
3+
/**
4+
* A class, struct, enum or protocol.
5+
*/
6+
class NominalType extends Generated::NominalType { }

swift/ql/lib/codeql/swift/elements/type/Type.qll

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
private import codeql.swift.generated.type.Type
2+
private import codeql.swift.elements.type.AnyGenericType
23

34
/**
45
* A Swift type.
@@ -42,16 +43,24 @@ class Type extends Generated::Type {
4243
Type getUnderlyingType() { result = this }
4344

4445
/**
45-
* Gets any base type of this type. For a `typealias`, this is a base type
46-
* of the aliased type. For example in the following code, both `B` and
47-
* `B_alias` have base type `A`.
46+
* Gets any base type of this type. Expands protocols added in extensions and expands
47+
* type aliases. For example in the following code, `B` has base type `A`:
4848
* ```
49-
* class A {}
49+
* typealias A_alias = A
5050
*
51-
* class B : A {}
51+
* class B : A_alias {}
52+
* ```
53+
*/
54+
Type getABaseType() { result = this.(AnyGenericType).getDeclaration().getABaseType() }
55+
56+
/**
57+
* Gets a type derived from this type. Expands type aliases, for example in the following
58+
* code, `B` derives from type `A`.
59+
* ```
60+
* typealias A_alias = A
5261
*
53-
* typealias B_alias = B
62+
* class B : A_alias {}
5463
* ```
5564
*/
56-
Type getABaseType() { none() }
65+
Type getADerivedType() { result.getABaseType() = this }
5766
}

swift/ql/lib/codeql/swift/elements/type/TypeAliasType.qll

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
private import codeql.swift.elements.type.Type
22
private import codeql.swift.generated.type.TypeAliasType
33

4+
/**
5+
* A type alias to another type. For example:
6+
* ```
7+
* typealias MyInt = Int
8+
* ```
9+
*/
410
class TypeAliasType extends Generated::TypeAliasType {
511
/**
612
* Gets the aliased type of this type alias type.
@@ -13,6 +19,4 @@ class TypeAliasType extends Generated::TypeAliasType {
1319
Type getAliasedType() { result = this.getDecl().getAliasedType() }
1420

1521
override Type getUnderlyingType() { result = this.getAliasedType().getUnderlyingType() }
16-
17-
override Type getABaseType() { result = this.getAliasedType().getABaseType() }
1822
}

0 commit comments

Comments
 (0)