Skip to content

Commit a79c32a

Browse files
committed
unified: Bulk imports
1 parent 50f934b commit a79c32a

5 files changed

Lines changed: 39 additions & 4 deletions

File tree

unified/ql/lib/codeql/unified/internal/LocalNameBinding.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,9 @@ private module LocalNameBindingInput implements LocalNameBindingInputSig<Locatio
326326
scope = any(TopLevel t) // Global module names are in scope here
327327
or
328328
scope = any(TopLevel t).getBody() // Imported names are in scope here
329+
or
330+
// Scopes with a bulk-import have uncertain members
331+
bindingContext(any(BulkImportingPattern b), scope, _)
329332
}
330333
}
331334

unified/ql/lib/codeql/unified/internal/NameBindingPlugin.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class NameBindingPlugin extends Unit {
2020
* Need only be implemented for members that occur in the context of class or top-level, as other
2121
* contexts are considered local already.
2222
*/
23-
predicate isPrivateToLocalScope(Member member) { none() }
23+
predicate isPrivateToLocalScope(Stmt member) { none() }
2424
}
2525

2626
/** Holds if `member` is an instance member. */
@@ -32,7 +32,7 @@ predicate isInstanceMember(Member member) {
3232
}
3333

3434
/** Holds if `member` is only visible in its local scope. */
35-
predicate isPrivateToLocalScope(Member member) {
35+
predicate isPrivateToLocalScope(Stmt member) {
3636
any(NameBindingPlugin p).isPrivateToLocalScope(member)
3737
}
3838

unified/ql/lib/codeql/unified/internal/NameBindingPluginSwift.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@ class NameBindingPluginSwift extends NameBindingPlugin {
1313
not member.hasModifier(["static", "class", "enum_case"])
1414
}
1515

16-
override predicate isPrivateToLocalScope(Member member) {
16+
override predicate isPrivateToLocalScope(Stmt member) {
1717
// Private top-level members
1818
member = any(TopLevel top).getBody().getAStmt() and
1919
member.hasModifier(["private", "fileprivate"])
20+
or
21+
// Imports are always file-local
22+
member instanceof ImportDeclaration
2023
//
2124
// Note: Private class members can be seen within type-extensions in the same file,
2225
// so we can't declare those private to their local scope.

unified/ql/lib/codeql/unified/internal/StaticNameBinding.qll

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ private import codeql.unified.internal.NameBindingPlugin
88

99
private newtype TNameBindingNode =
1010
TIdentifier(Identifier n) or
11+
TBulkImport(BulkImportingPattern p) or
1112
TLocalName(LocalName local) or
1213
TExportedNamespace(ClassLikeDeclaration cls) or
1314
TLocalNamespace(AstNode n) {
@@ -26,6 +27,8 @@ class NameBindingNode extends TNameBindingNode {
2627

2728
Identifier asIdentifier() { this.isIdentifier(result) }
2829

30+
predicate isBulkImport(BulkImportingPattern p) { this = TBulkImport(p) }
31+
2932
predicate isLocalName(LocalName local) { this = TLocalName(local) }
3033

3134
/** Holds if this represents the set of static members available in the given namespace. */
@@ -43,6 +46,8 @@ class NameBindingNode extends TNameBindingNode {
4346
string toString() {
4447
exists(Identifier n | this.isIdentifier(n) and result = "Identifier(" + n + ")")
4548
or
49+
exists(BulkImportingPattern p | this.isBulkImport(p) and result = "BulkImport(" + p + ")")
50+
or
4651
exists(LocalName local | this.isLocalName(local) and result = "LocalName(" + local + ")")
4752
or
4853
exists(ClassLikeDeclaration cls |
@@ -63,6 +68,8 @@ class NameBindingNode extends TNameBindingNode {
6368
Location getLocation() {
6469
exists(Identifier n | this.isIdentifier(n) and result = n.getLocation())
6570
or
71+
exists(BulkImportingPattern p | this.isBulkImport(p) and result = p.getLocation())
72+
or
6673
exists(LocalName local | this.isLocalName(local) and result = local.getLocation())
6774
or
6875
exists(ClassLikeDeclaration cls | this.isExportedNamespace(cls) and result = cls.getLocation())
@@ -86,7 +93,11 @@ Identifier getIdentifierFromRef(AstNode n) {
8693
result = n.(NamedTypeExpr).getName()
8794
}
8895

89-
NameBindingNode getNodeFromRef(AstNode n) { result.isIdentifier(getIdentifierFromRef(n)) }
96+
NameBindingNode getNodeFromRef(AstNode n) {
97+
result.isIdentifier(getIdentifierFromRef(n))
98+
or
99+
result.isBulkImport(n)
100+
}
90101

91102
NameBindingNode getModuleNodeFromFile(File f) {
92103
exists(ModuleScopeRepr mod |
@@ -186,6 +197,20 @@ predicate valueStep(NameBindingNode node1, NameBindingNode node2) {
186197
node1 = getNodeFromRef(imprt.getImportedExpr()) and
187198
node2 = getNodeFromRef(imprt.getPattern())
188199
)
200+
or
201+
exists(BulkImportingPattern p, AstNode scope, AstNode declaration |
202+
bindingContext(p, scope, declaration) and
203+
node1 = getNodeFromRef(p)
204+
|
205+
node2 = getNodeFromUncertainScope(scope)
206+
or
207+
// Bulk re-exporting declarations
208+
exists(TopLevel top |
209+
declaration = top.getBody().getAStmt() and
210+
not isPrivateToLocalScope(declaration) and
211+
node2 = getModuleNodeFromFile(top.getFile())
212+
)
213+
)
189214
}
190215

191216
predicate inheritanceStep(NameBindingNode supertype, NameBindingNode subtype) {
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import Target2
2+
3+
private let x1: B.C; // $ access=Target2.B access=Target2.B.C
4+
private let x2: Target2.B.C; // $ access=Target2.B access=Target2.B.C

0 commit comments

Comments
 (0)