Skip to content

Commit 168b66d

Browse files
committed
Rust: Handle unqualified UseTrees in path resolution
1 parent 39dd3ac commit 168b66d

File tree

3 files changed

+63
-7
lines changed

3 files changed

+63
-7
lines changed

rust/ql/lib/codeql/rust/internal/PathResolution.qll

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,6 +1457,27 @@ private predicate crateDependencyEdge(SourceFileItemNode file, string name, Crat
14571457
not hasDeclOrDep(file, name)
14581458
}
14591459

1460+
/**
1461+
* Gets a `UseTree` that is nested under `tree`, and which needs to be resolved
1462+
* relative to the path of `tree`.
1463+
*
1464+
* `tree` either has a path or is a direct child of some `use` statement.
1465+
*/
1466+
private UseTree getAUseTreeUseTree(UseTree tree) {
1467+
result = tree.getUseTreeList().getAUseTree() and
1468+
(
1469+
tree.hasPath()
1470+
or
1471+
tree = any(Use u).getUseTree()
1472+
)
1473+
or
1474+
exists(UseTree mid |
1475+
mid = getAUseTreeUseTree(tree) and
1476+
not mid.hasPath() and
1477+
result = mid.getUseTreeList().getAUseTree()
1478+
)
1479+
}
1480+
14601481
private predicate useTreeDeclares(UseTree tree, string name) {
14611482
not tree.isGlob() and
14621483
not exists(tree.getUseTreeList()) and
@@ -1470,7 +1491,7 @@ private predicate useTreeDeclares(UseTree tree, string name) {
14701491
or
14711492
exists(UseTree mid |
14721493
useTreeDeclares(mid, name) and
1473-
mid = tree.getUseTreeList().getAUseTree()
1494+
mid = getAUseTreeUseTree(tree)
14741495
)
14751496
}
14761497

@@ -1511,7 +1532,10 @@ class RelevantPath extends Path {
15111532
pragma[nomagic]
15121533
predicate isUnqualified(string name) {
15131534
not exists(this.getQualifier()) and
1514-
not this = any(UseTreeList list).getAUseTree().getPath().getQualifier*() and
1535+
not exists(UseTree tree |
1536+
tree.hasPath() and
1537+
this = getAUseTreeUseTree(tree).getPath().getQualifier*()
1538+
) and
15151539
name = this.getText()
15161540
}
15171541

@@ -1990,7 +2014,7 @@ private ItemNode resolveUseTreeListItem(Use use, UseTree tree, RelevantPath path
19902014
exists(UseOption useOpt | checkQualifiedVisibility(use, result, kind, useOpt) |
19912015
exists(UseTree midTree, ItemNode mid, string name |
19922016
mid = resolveUseTreeListItem(use, midTree) and
1993-
tree = midTree.getUseTreeList().getAUseTree() and
2017+
tree = getAUseTreeUseTree(midTree) and
19942018
isUseTreeSubPathUnqualified(tree, path, pragma[only_bind_into](name)) and
19952019
result = mid.getASuccessor(pragma[only_bind_into](name), kind, useOpt)
19962020
)
@@ -2010,14 +2034,31 @@ private ItemNode resolveUseTreeListItemQualifier(
20102034
name = path.getText()
20112035
}
20122036

2037+
private UseTree getAUseUseTree(Use use) {
2038+
result = use.getUseTree()
2039+
or
2040+
exists(UseTree root |
2041+
root = use.getUseTree() and
2042+
not root.hasPath() and
2043+
result = getAUseTreeUseTree(root)
2044+
)
2045+
}
2046+
20132047
pragma[nomagic]
20142048
private ItemNode resolveUseTreeListItem(Use use, UseTree tree) {
20152049
exists(Path path | path = tree.getPath() |
2016-
tree = use.getUseTree() and
2050+
tree = getAUseUseTree(use) and
20172051
result = resolvePathCand(path)
20182052
or
20192053
result = resolveUseTreeListItem(use, tree, path, _)
20202054
)
2055+
or
2056+
exists(UseTree midTree |
2057+
result = resolveUseTreeListItem(use, midTree) and
2058+
tree = getAUseTreeUseTree(midTree) and
2059+
tree.isGlob() and
2060+
not tree.hasPath()
2061+
)
20212062
}
20222063

20232064
/** Holds if `use` imports `item` as `name`. */
@@ -2159,6 +2200,16 @@ private module Debug {
21592200
result = resolvePath(path)
21602201
}
21612202

2203+
ItemNode debugResolveUseTreeListItem(Use use, UseTree tree, RelevantPath path, SuccessorKind kind) {
2204+
use = getRelevantLocatable() and
2205+
result = resolveUseTreeListItem(use, tree, path, kind)
2206+
}
2207+
2208+
ItemNode debugResolveUseTreeListItem(Use use, UseTree tree) {
2209+
use = getRelevantLocatable() and
2210+
result = resolveUseTreeListItem(use, tree)
2211+
}
2212+
21622213
predicate debugUseImportEdge(Use use, string name, ItemNode item, SuccessorKind kind) {
21632214
use = getRelevantLocatable() and
21642215
useImportEdge(use, name, item, kind)

rust/ql/test/library-tests/path-resolution/main.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
mod my; // I1
22

33
#[rustfmt::skip]
4-
use {{{my::{{self as my_alias, *}}}}}; // $ MISSING: item=I1
4+
use {{{my::{{self as my_alias, *}}}}}; // $ item=I1
55

66
use my::nested::nested1::nested2::*; // $ item=I3
77

@@ -816,8 +816,8 @@ fn main() {
816816
nested6::f(); // $ item=I116
817817
nested8::f(); // $ item=I119
818818
my3::f(); // $ item=I200
819-
nested_f(); // $ MISSING: item=I201
820-
my_alias::nested_f(); // $ MISSING: item=I201
819+
nested_f(); // $ item=I201
820+
my_alias::nested_f(); // $ item=I201
821821
m18::m19::m20::g(); // $ item=I103
822822
m23::f(); // $ item=I108
823823
m24::f(); // $ item=I121

rust/ql/test/library-tests/path-resolution/path-resolution.expected

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ mod
4747
| my/nested.rs:1:1:17:1 | mod nested1 |
4848
| my/nested.rs:2:5:11:5 | mod nested2 |
4949
resolvePath
50+
| main.rs:4:8:4:9 | my | main.rs:1:1:1:7 | mod my |
51+
| main.rs:4:14:4:17 | self | main.rs:1:1:1:7 | mod my |
5052
| main.rs:6:5:6:6 | my | main.rs:1:1:1:7 | mod my |
5153
| main.rs:6:5:6:14 | ...::nested | my.rs:1:1:1:15 | mod nested |
5254
| main.rs:6:5:6:23 | ...::nested1 | my/nested.rs:1:1:17:1 | mod nested1 |
@@ -447,6 +449,9 @@ resolvePath
447449
| main.rs:817:5:817:14 | ...::f | my2/nested2.rs:23:9:25:9 | fn f |
448450
| main.rs:818:5:818:7 | my3 | my2/mod.rs:20:1:20:12 | mod my3 |
449451
| main.rs:818:5:818:10 | ...::f | my2/my3/mod.rs:1:1:5:1 | fn f |
452+
| main.rs:819:5:819:12 | nested_f | my/my4/my5/mod.rs:1:1:3:1 | fn f |
453+
| main.rs:820:5:820:12 | my_alias | main.rs:1:1:1:7 | mod my |
454+
| main.rs:820:5:820:22 | ...::nested_f | my/my4/my5/mod.rs:1:1:3:1 | fn f |
450455
| main.rs:821:5:821:7 | m18 | main.rs:555:1:573:1 | mod m18 |
451456
| main.rs:821:5:821:12 | ...::m19 | main.rs:560:5:572:5 | mod m19 |
452457
| main.rs:821:5:821:17 | ...::m20 | main.rs:565:9:571:9 | mod m20 |

0 commit comments

Comments
 (0)