Skip to content

Commit 0bfc7cf

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

File tree

3 files changed

+65
-7
lines changed

3 files changed

+65
-7
lines changed

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

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,6 +1457,28 @@ 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` is restricted to either having a path or being a direct child of some
1465+
* `use` statement.
1466+
*/
1467+
private UseTree getAUseTreeUseTree(UseTree tree) {
1468+
result = tree.getUseTreeList().getAUseTree() and
1469+
(
1470+
tree.hasPath()
1471+
or
1472+
tree = any(Use u).getUseTree()
1473+
)
1474+
or
1475+
exists(UseTree mid |
1476+
mid = getAUseTreeUseTree(tree) and
1477+
not mid.hasPath() and
1478+
result = mid.getUseTreeList().getAUseTree()
1479+
)
1480+
}
1481+
14601482
private predicate useTreeDeclares(UseTree tree, string name) {
14611483
not tree.isGlob() and
14621484
not exists(tree.getUseTreeList()) and
@@ -1470,7 +1492,7 @@ private predicate useTreeDeclares(UseTree tree, string name) {
14701492
or
14711493
exists(UseTree mid |
14721494
useTreeDeclares(mid, name) and
1473-
mid = tree.getUseTreeList().getAUseTree()
1495+
mid = getAUseTreeUseTree(tree)
14741496
)
14751497
}
14761498

@@ -1511,7 +1533,10 @@ class RelevantPath extends Path {
15111533
pragma[nomagic]
15121534
predicate isUnqualified(string name) {
15131535
not exists(this.getQualifier()) and
1514-
not this = any(UseTreeList list).getAUseTree().getPath().getQualifier*() and
1536+
not exists(UseTree tree |
1537+
tree.hasPath() and
1538+
this = getAUseTreeUseTree(tree).getPath().getQualifier*()
1539+
) and
15151540
name = this.getText()
15161541
}
15171542

@@ -1990,7 +2015,7 @@ private ItemNode resolveUseTreeListItem(Use use, UseTree tree, RelevantPath path
19902015
exists(UseOption useOpt | checkQualifiedVisibility(use, result, kind, useOpt) |
19912016
exists(UseTree midTree, ItemNode mid, string name |
19922017
mid = resolveUseTreeListItem(use, midTree) and
1993-
tree = midTree.getUseTreeList().getAUseTree() and
2018+
tree = getAUseTreeUseTree(midTree) and
19942019
isUseTreeSubPathUnqualified(tree, path, pragma[only_bind_into](name)) and
19952020
result = mid.getASuccessor(pragma[only_bind_into](name), kind, useOpt)
19962021
)
@@ -2010,14 +2035,32 @@ private ItemNode resolveUseTreeListItemQualifier(
20102035
name = path.getText()
20112036
}
20122037

2038+
private UseTree getAUseUseTree(Use use) {
2039+
result = use.getUseTree()
2040+
or
2041+
exists(UseTree root |
2042+
root = use.getUseTree() and
2043+
not root.hasPath() and
2044+
result = getAUseTreeUseTree(root)
2045+
)
2046+
}
2047+
20132048
pragma[nomagic]
20142049
private ItemNode resolveUseTreeListItem(Use use, UseTree tree) {
20152050
exists(Path path | path = tree.getPath() |
2016-
tree = use.getUseTree() and
2051+
tree = getAUseUseTree(use) and
20172052
result = resolvePathCand(path)
20182053
or
20192054
result = resolveUseTreeListItem(use, tree, path, _)
20202055
)
2056+
or
2057+
exists(UseTree midTree |
2058+
// `use foo::{bar, *}`; midTree = `foo` and tree = `*`
2059+
result = resolveUseTreeListItem(use, midTree) and
2060+
tree = getAUseTreeUseTree(midTree) and
2061+
tree.isGlob() and
2062+
not tree.hasPath()
2063+
)
20212064
}
20222065

20232066
/** Holds if `use` imports `item` as `name`. */
@@ -2159,6 +2202,16 @@ private module Debug {
21592202
result = resolvePath(path)
21602203
}
21612204

2205+
ItemNode debugResolveUseTreeListItem(Use use, UseTree tree, RelevantPath path, SuccessorKind kind) {
2206+
use = getRelevantLocatable() and
2207+
result = resolveUseTreeListItem(use, tree, path, kind)
2208+
}
2209+
2210+
ItemNode debugResolveUseTreeListItem(Use use, UseTree tree) {
2211+
use = getRelevantLocatable() and
2212+
result = resolveUseTreeListItem(use, tree)
2213+
}
2214+
21622215
predicate debugUseImportEdge(Use use, string name, ItemNode item, SuccessorKind kind) {
21632216
use = getRelevantLocatable() and
21642217
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)