Skip to content

Commit 179d0b3

Browse files
committed
Ruby: make up qnames for top-level namespaces
1 parent a59a404 commit 179d0b3

File tree

5 files changed

+94
-26
lines changed

5 files changed

+94
-26
lines changed

ruby/ql/lib/codeql/ruby/ast/internal/Module.qll

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ private module Cached {
2121
qName = getAnAssumedGlobalConst()
2222
or
2323
qName = namespaceDeclaration(_)
24+
or
25+
qName = getAnAssumedGlobalNamespacePrefix(_)
2426
} or
2527
TUnresolved(Namespace n) { not exists(namespaceDeclaration(n)) }
2628

@@ -36,6 +38,8 @@ private module Cached {
3638
TResolved(container) = resolveConstantReadAccess(n.getScopeExpr()) and
3739
result = scopeAppend(container, n.getName())
3840
)
41+
or
42+
result = getAnAssumedGlobalNamespacePrefix(n)
3943
}
4044

4145
cached
@@ -412,13 +416,43 @@ private module ResolveImpl {
412416
)
413417
}
414418

419+
private ConstantAccess getANamespaceScopeInTopLevel() {
420+
result.(Namespace).getEnclosingModule() instanceof Toplevel
421+
or
422+
result = getANamespaceScopeInTopLevel().getScopeExpr()
423+
}
424+
425+
/**
426+
* Gets the syntactical qualified name of the given constant access, which must be a top-level
427+
* namespace or scope prefix thereof.
428+
*
429+
* For example, for `module A::B::C` this gets `A`, `A::B`, and `A::B::C` for the two prefixes
430+
* and the module itself, respectively.
431+
*/
432+
string getAnAssumedGlobalNamespacePrefix(ConstantAccess access) {
433+
access = getANamespaceScopeInTopLevel() and
434+
(
435+
not exists(access.getScopeExpr()) and
436+
result = access.getName()
437+
or
438+
result =
439+
scopeAppend(getAnAssumedGlobalNamespacePrefix(access.getScopeExpr()), access.getName())
440+
)
441+
}
442+
415443
pragma[nomagic]
416444
private string isDefinedConstantNonRec(string container, string name) {
417445
result = resolveConstantWriteAccessNonRec(_, container, name)
418446
or
419447
result = [builtin(), getAnAssumedGlobalConst()] and
420448
name = result and
421449
container = "Object"
450+
or
451+
exists(ConstantAccess access |
452+
container = getAnAssumedGlobalNamespacePrefix(access.getScopeExpr()) and
453+
name = access.getName() and
454+
result = getAnAssumedGlobalNamespacePrefix(access)
455+
)
422456
}
423457

424458
pragma[nomagic]

ruby/ql/test/library-tests/modules/ancestors.expected

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@
3636
#-----| TrueClass
3737
#-----| super -> Object
3838

39+
#-----| UnresolvedNamespace::X1
40+
41+
#-----| UnresolvedNamespace::X1::X2
42+
43+
#-----| UnresolvedNamespace::X1::X2::X3
44+
3945
calls.rb:
4046
# 21| M
4147

@@ -273,11 +279,11 @@ unresolved_subclass.rb:
273279
# 11| UnresolvedNamespace::A
274280
#-----| super -> Object
275281

276-
# 14| ...::Subclass1
282+
# 14| UnresolvedNamespace::X1::X2::X3::Subclass1
277283
#-----| super -> ResolvableBaseClass
278284

279-
# 17| ...::Subclass2
280-
#-----| super -> Object
285+
# 17| UnresolvedNamespace::X1::X2::X3::Subclass2
286+
#-----| super -> UnresolvedNamespace::X1::X2::X3::Subclass1
281287

282-
# 21| ...::A
288+
# 21| UnresolvedNamespace::X1::X2::X3::A
283289
#-----| super -> Object

ruby/ql/test/library-tests/modules/methods.expected

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -660,15 +660,15 @@ lookupMethod
660660
| unresolved_subclass.rb:11:1:12:3 | UnresolvedNamespace::A | new | calls.rb:117:5:117:16 | new |
661661
| unresolved_subclass.rb:11:1:12:3 | UnresolvedNamespace::A | puts | calls.rb:102:5:102:30 | puts |
662662
| unresolved_subclass.rb:11:1:12:3 | UnresolvedNamespace::A | to_s | calls.rb:172:5:173:7 | to_s |
663-
| unresolved_subclass.rb:14:1:15:3 | ...::Subclass1 | new | calls.rb:117:5:117:16 | new |
664-
| unresolved_subclass.rb:14:1:15:3 | ...::Subclass1 | puts | calls.rb:102:5:102:30 | puts |
665-
| unresolved_subclass.rb:14:1:15:3 | ...::Subclass1 | to_s | calls.rb:172:5:173:7 | to_s |
666-
| unresolved_subclass.rb:17:1:18:3 | ...::Subclass2 | new | calls.rb:117:5:117:16 | new |
667-
| unresolved_subclass.rb:17:1:18:3 | ...::Subclass2 | puts | calls.rb:102:5:102:30 | puts |
668-
| unresolved_subclass.rb:17:1:18:3 | ...::Subclass2 | to_s | calls.rb:172:5:173:7 | to_s |
669-
| unresolved_subclass.rb:21:1:22:3 | ...::A | new | calls.rb:117:5:117:16 | new |
670-
| unresolved_subclass.rb:21:1:22:3 | ...::A | puts | calls.rb:102:5:102:30 | puts |
671-
| unresolved_subclass.rb:21:1:22:3 | ...::A | to_s | calls.rb:172:5:173:7 | to_s |
663+
| unresolved_subclass.rb:14:1:15:3 | UnresolvedNamespace::X1::X2::X3::Subclass1 | new | calls.rb:117:5:117:16 | new |
664+
| unresolved_subclass.rb:14:1:15:3 | UnresolvedNamespace::X1::X2::X3::Subclass1 | puts | calls.rb:102:5:102:30 | puts |
665+
| unresolved_subclass.rb:14:1:15:3 | UnresolvedNamespace::X1::X2::X3::Subclass1 | to_s | calls.rb:172:5:173:7 | to_s |
666+
| unresolved_subclass.rb:17:1:18:3 | UnresolvedNamespace::X1::X2::X3::Subclass2 | new | calls.rb:117:5:117:16 | new |
667+
| unresolved_subclass.rb:17:1:18:3 | UnresolvedNamespace::X1::X2::X3::Subclass2 | puts | calls.rb:102:5:102:30 | puts |
668+
| unresolved_subclass.rb:17:1:18:3 | UnresolvedNamespace::X1::X2::X3::Subclass2 | to_s | calls.rb:172:5:173:7 | to_s |
669+
| unresolved_subclass.rb:21:1:22:3 | UnresolvedNamespace::X1::X2::X3::A | new | calls.rb:117:5:117:16 | new |
670+
| unresolved_subclass.rb:21:1:22:3 | UnresolvedNamespace::X1::X2::X3::A | puts | calls.rb:102:5:102:30 | puts |
671+
| unresolved_subclass.rb:21:1:22:3 | UnresolvedNamespace::X1::X2::X3::A | to_s | calls.rb:172:5:173:7 | to_s |
672672
enclosingMethod
673673
| calls.rb:2:5:2:14 | call to puts | calls.rb:1:1:3:3 | foo |
674674
| calls.rb:2:5:2:14 | self | calls.rb:1:1:3:3 | foo |

ruby/ql/test/library-tests/modules/modules.expected

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ getModule
5151
| file://:0:0:0:0 | Symbol |
5252
| file://:0:0:0:0 | TrueClass |
5353
| file://:0:0:0:0 | UnresolvedNamespace |
54+
| file://:0:0:0:0 | UnresolvedNamespace::X1 |
55+
| file://:0:0:0:0 | UnresolvedNamespace::X1::X2 |
56+
| file://:0:0:0:0 | UnresolvedNamespace::X1::X2::X3 |
5457
| hello.rb:1:1:8:3 | EnglishWords |
5558
| hello.rb:11:1:16:3 | Greeting |
5659
| hello.rb:18:1:22:3 | HelloWorld |
@@ -97,9 +100,9 @@ getModule
97100
| unresolved_subclass.rb:4:1:5:3 | UnresolvedNamespace::Subclass1 |
98101
| unresolved_subclass.rb:7:1:8:3 | UnresolvedNamespace::Subclass2 |
99102
| unresolved_subclass.rb:11:1:12:3 | UnresolvedNamespace::A |
100-
| unresolved_subclass.rb:14:1:15:3 | ...::Subclass1 |
101-
| unresolved_subclass.rb:17:1:18:3 | ...::Subclass2 |
102-
| unresolved_subclass.rb:21:1:22:3 | ...::A |
103+
| unresolved_subclass.rb:14:1:15:3 | UnresolvedNamespace::X1::X2::X3::Subclass1 |
104+
| unresolved_subclass.rb:17:1:18:3 | UnresolvedNamespace::X1::X2::X3::Subclass2 |
105+
| unresolved_subclass.rb:21:1:22:3 | UnresolvedNamespace::X1::X2::X3::A |
103106
getADeclaration
104107
| calls.rb:21:1:34:3 | M | calls.rb:21:1:34:3 | M |
105108
| calls.rb:43:1:58:3 | C | calls.rb:43:1:58:3 | C |
@@ -200,9 +203,9 @@ getADeclaration
200203
| unresolved_subclass.rb:4:1:5:3 | UnresolvedNamespace::Subclass1 | unresolved_subclass.rb:4:1:5:3 | Subclass1 |
201204
| unresolved_subclass.rb:7:1:8:3 | UnresolvedNamespace::Subclass2 | unresolved_subclass.rb:7:1:8:3 | Subclass2 |
202205
| unresolved_subclass.rb:11:1:12:3 | UnresolvedNamespace::A | unresolved_subclass.rb:11:1:12:3 | A |
203-
| unresolved_subclass.rb:14:1:15:3 | ...::Subclass1 | unresolved_subclass.rb:14:1:15:3 | Subclass1 |
204-
| unresolved_subclass.rb:17:1:18:3 | ...::Subclass2 | unresolved_subclass.rb:17:1:18:3 | Subclass2 |
205-
| unresolved_subclass.rb:21:1:22:3 | ...::A | unresolved_subclass.rb:21:1:22:3 | A |
206+
| unresolved_subclass.rb:14:1:15:3 | UnresolvedNamespace::X1::X2::X3::Subclass1 | unresolved_subclass.rb:14:1:15:3 | Subclass1 |
207+
| unresolved_subclass.rb:17:1:18:3 | UnresolvedNamespace::X1::X2::X3::Subclass2 | unresolved_subclass.rb:17:1:18:3 | Subclass2 |
208+
| unresolved_subclass.rb:21:1:22:3 | UnresolvedNamespace::X1::X2::X3::A | unresolved_subclass.rb:21:1:22:3 | A |
206209
getSuperClass
207210
| calls.rb:43:1:58:3 | C | calls.rb:115:1:118:3 | Object |
208211
| calls.rb:65:1:69:3 | D | calls.rb:43:1:58:3 | C |
@@ -265,9 +268,9 @@ getSuperClass
265268
| unresolved_subclass.rb:4:1:5:3 | UnresolvedNamespace::Subclass1 | unresolved_subclass.rb:1:1:2:3 | ResolvableBaseClass |
266269
| unresolved_subclass.rb:7:1:8:3 | UnresolvedNamespace::Subclass2 | unresolved_subclass.rb:4:1:5:3 | UnresolvedNamespace::Subclass1 |
267270
| unresolved_subclass.rb:11:1:12:3 | UnresolvedNamespace::A | calls.rb:115:1:118:3 | Object |
268-
| unresolved_subclass.rb:14:1:15:3 | ...::Subclass1 | unresolved_subclass.rb:1:1:2:3 | ResolvableBaseClass |
269-
| unresolved_subclass.rb:17:1:18:3 | ...::Subclass2 | calls.rb:115:1:118:3 | Object |
270-
| unresolved_subclass.rb:21:1:22:3 | ...::A | calls.rb:115:1:118:3 | Object |
271+
| unresolved_subclass.rb:14:1:15:3 | UnresolvedNamespace::X1::X2::X3::Subclass1 | unresolved_subclass.rb:1:1:2:3 | ResolvableBaseClass |
272+
| unresolved_subclass.rb:17:1:18:3 | UnresolvedNamespace::X1::X2::X3::Subclass2 | unresolved_subclass.rb:14:1:15:3 | UnresolvedNamespace::X1::X2::X3::Subclass1 |
273+
| unresolved_subclass.rb:21:1:22:3 | UnresolvedNamespace::X1::X2::X3::A | calls.rb:115:1:118:3 | Object |
271274
getAPrependedModule
272275
| calls.rb:115:1:118:3 | Object | calls.rb:171:1:174:3 | A |
273276
| calls.rb:171:1:174:3 | A | toplevel_self_singleton.rb:2:5:5:7 | A::B |
@@ -429,11 +432,27 @@ resolveConstantReadAccess
429432
| unresolved_subclass.rb:11:7:11:25 | UnresolvedNamespace | UnresolvedNamespace |
430433
| unresolved_subclass.rb:11:32:11:50 | UnresolvedNamespace | UnresolvedNamespace |
431434
| unresolved_subclass.rb:14:7:14:25 | UnresolvedNamespace | UnresolvedNamespace |
435+
| unresolved_subclass.rb:14:7:14:29 | X1 | UnresolvedNamespace::X1 |
436+
| unresolved_subclass.rb:14:7:14:33 | X2 | UnresolvedNamespace::X1::X2 |
437+
| unresolved_subclass.rb:14:7:14:37 | X3 | UnresolvedNamespace::X1::X2::X3 |
432438
| unresolved_subclass.rb:14:52:14:70 | ResolvableBaseClass | ResolvableBaseClass |
433439
| unresolved_subclass.rb:17:7:17:25 | UnresolvedNamespace | UnresolvedNamespace |
440+
| unresolved_subclass.rb:17:7:17:29 | X1 | UnresolvedNamespace::X1 |
441+
| unresolved_subclass.rb:17:7:17:33 | X2 | UnresolvedNamespace::X1::X2 |
442+
| unresolved_subclass.rb:17:7:17:37 | X3 | UnresolvedNamespace::X1::X2::X3 |
434443
| unresolved_subclass.rb:17:52:17:70 | UnresolvedNamespace | UnresolvedNamespace |
444+
| unresolved_subclass.rb:17:52:17:74 | X1 | UnresolvedNamespace::X1 |
445+
| unresolved_subclass.rb:17:52:17:78 | X2 | UnresolvedNamespace::X1::X2 |
446+
| unresolved_subclass.rb:17:52:17:82 | X3 | UnresolvedNamespace::X1::X2::X3 |
447+
| unresolved_subclass.rb:17:52:17:93 | Subclass1 | UnresolvedNamespace::X1::X2::X3::Subclass1 |
435448
| unresolved_subclass.rb:21:7:21:25 | UnresolvedNamespace | UnresolvedNamespace |
449+
| unresolved_subclass.rb:21:7:21:29 | X1 | UnresolvedNamespace::X1 |
450+
| unresolved_subclass.rb:21:7:21:33 | X2 | UnresolvedNamespace::X1::X2 |
451+
| unresolved_subclass.rb:21:7:21:37 | X3 | UnresolvedNamespace::X1::X2::X3 |
436452
| unresolved_subclass.rb:21:44:21:62 | UnresolvedNamespace | UnresolvedNamespace |
453+
| unresolved_subclass.rb:21:44:21:66 | X1 | UnresolvedNamespace::X1 |
454+
| unresolved_subclass.rb:21:44:21:70 | X2 | UnresolvedNamespace::X1::X2 |
455+
| unresolved_subclass.rb:21:44:21:74 | X3 | UnresolvedNamespace::X1::X2::X3 |
437456
resolveConstantWriteAccess
438457
| calls.rb:21:1:34:3 | M | M |
439458
| calls.rb:43:1:58:3 | C | C |
@@ -538,6 +557,9 @@ resolveConstantWriteAccess
538557
| unresolved_subclass.rb:4:1:5:3 | Subclass1 | UnresolvedNamespace::Subclass1 |
539558
| unresolved_subclass.rb:7:1:8:3 | Subclass2 | UnresolvedNamespace::Subclass2 |
540559
| unresolved_subclass.rb:11:1:12:3 | A | UnresolvedNamespace::A |
560+
| unresolved_subclass.rb:14:1:15:3 | Subclass1 | UnresolvedNamespace::X1::X2::X3::Subclass1 |
561+
| unresolved_subclass.rb:17:1:18:3 | Subclass2 | UnresolvedNamespace::X1::X2::X3::Subclass2 |
562+
| unresolved_subclass.rb:21:1:22:3 | A | UnresolvedNamespace::X1::X2::X3::A |
541563
enclosingModule
542564
| calls.rb:1:1:3:3 | foo | calls.rb:1:1:651:24 | calls.rb |
543565
| calls.rb:2:5:2:14 | call to puts | calls.rb:1:1:651:24 | calls.rb |

ruby/ql/test/library-tests/modules/superclasses.expected

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@
3636
#-----| TrueClass
3737
#-----| -> Object
3838

39+
#-----| UnresolvedNamespace::X1
40+
41+
#-----| UnresolvedNamespace::X1::X2
42+
43+
#-----| UnresolvedNamespace::X1::X2::X3
44+
3945
calls.rb:
4046
# 21| M
4147

@@ -263,11 +269,11 @@ unresolved_subclass.rb:
263269
# 11| UnresolvedNamespace::A
264270
#-----| -> Object
265271

266-
# 14| ...::Subclass1
272+
# 14| UnresolvedNamespace::X1::X2::X3::Subclass1
267273
#-----| -> ResolvableBaseClass
268274

269-
# 17| ...::Subclass2
270-
#-----| -> Object
275+
# 17| UnresolvedNamespace::X1::X2::X3::Subclass2
276+
#-----| -> UnresolvedNamespace::X1::X2::X3::Subclass1
271277

272-
# 21| ...::A
278+
# 21| UnresolvedNamespace::X1::X2::X3::A
273279
#-----| -> Object

0 commit comments

Comments
 (0)