Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 52 additions & 4 deletions rust/ql/lib/codeql/rust/internal/PathResolution.qll
Original file line number Diff line number Diff line change
Expand Up @@ -1457,6 +1457,24 @@ private predicate crateDependencyEdge(SourceFileItemNode file, string name, Crat
not hasDeclOrDep(file, name)
}

/**
* Gets a `UseTree` that is nested under `tree`, and which needs to be resolved
* relative to the path of `tree`.
*
* `tree` is restricted to either having a path or being a direct child of some
* `use` statement without a path.
*/
private UseTree getAUseTreeUseTree(UseTree tree) {
result = tree.getUseTreeList().getAUseTree() and
(if tree.hasPath() then any() else tree = any(Use u).getUseTree())
or
exists(UseTree mid |
mid = getAUseTreeUseTree(tree) and
not mid.hasPath() and
result = mid.getUseTreeList().getAUseTree()
)
}

private predicate useTreeDeclares(UseTree tree, string name) {
not tree.isGlob() and
not exists(tree.getUseTreeList()) and
Expand All @@ -1470,7 +1488,7 @@ private predicate useTreeDeclares(UseTree tree, string name) {
or
exists(UseTree mid |
useTreeDeclares(mid, name) and
mid = tree.getUseTreeList().getAUseTree()
mid = getAUseTreeUseTree(tree)
)
}

Expand Down Expand Up @@ -1511,7 +1529,10 @@ class RelevantPath extends Path {
pragma[nomagic]
predicate isUnqualified(string name) {
not exists(this.getQualifier()) and
not this = any(UseTreeList list).getAUseTree().getPath().getQualifier*() and
not exists(UseTree tree |
tree.hasPath() and
this = getAUseTreeUseTree(tree).getPath().getQualifier*()
) and
name = this.getText()
}

Expand Down Expand Up @@ -1990,7 +2011,7 @@ private ItemNode resolveUseTreeListItem(Use use, UseTree tree, RelevantPath path
exists(UseOption useOpt | checkQualifiedVisibility(use, result, kind, useOpt) |
exists(UseTree midTree, ItemNode mid, string name |
mid = resolveUseTreeListItem(use, midTree) and
tree = midTree.getUseTreeList().getAUseTree() and
tree = getAUseTreeUseTree(midTree) and
isUseTreeSubPathUnqualified(tree, path, pragma[only_bind_into](name)) and
result = mid.getASuccessor(pragma[only_bind_into](name), kind, useOpt)
)
Expand All @@ -2010,14 +2031,31 @@ private ItemNode resolveUseTreeListItemQualifier(
name = path.getText()
}

private UseTree getAUseUseTree(Use use) {
exists(UseTree root | root = use.getUseTree() |
result = root
or
not root.hasPath() and
result = getAUseTreeUseTree(root)
)
}

pragma[nomagic]
private ItemNode resolveUseTreeListItem(Use use, UseTree tree) {
exists(Path path | path = tree.getPath() |
tree = use.getUseTree() and
tree = getAUseUseTree(use) and
result = resolvePathCand(path)
or
result = resolveUseTreeListItem(use, tree, path, _)
)
or
exists(UseTree midTree |
// `use foo::{bar, *}`; midTree = `foo` and tree = `*`
result = resolveUseTreeListItem(use, midTree) and
tree = getAUseTreeUseTree(midTree) and
tree.isGlob() and
not tree.hasPath()
)
}

/** Holds if `use` imports `item` as `name`. */
Expand Down Expand Up @@ -2159,6 +2197,16 @@ private module Debug {
result = resolvePath(path)
}

ItemNode debugResolveUseTreeListItem(Use use, UseTree tree, RelevantPath path, SuccessorKind kind) {
use = getRelevantLocatable() and
result = resolveUseTreeListItem(use, tree, path, kind)
}

ItemNode debugResolveUseTreeListItem(Use use, UseTree tree) {
use = getRelevantLocatable() and
result = resolveUseTreeListItem(use, tree)
}

predicate debugUseImportEdge(Use use, string name, ItemNode item, SuccessorKind kind) {
use = getRelevantLocatable() and
useImportEdge(use, name, item, kind)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
multipleCallTargets
| main.rs:125:9:125:11 | f(...) |
| main.rs:365:9:367:16 | ...::f(...) |
| main.rs:368:9:370:16 | ...::f(...) |
| main.rs:447:9:451:16 | ...::f(...) |
| main.rs:452:9:456:16 | ...::f(...) |
| main.rs:126:9:126:11 | f(...) |
| main.rs:366:9:368:16 | ...::f(...) |
| main.rs:369:9:371:16 | ...::f(...) |
| main.rs:448:9:452:16 | ...::f(...) |
| main.rs:453:9:457:16 | ...::f(...) |
4 changes: 3 additions & 1 deletion rust/ql/test/library-tests/path-resolution/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod my; // I1

use my::*; // $ item=I1
#[rustfmt::skip]
use {{{my::{{self as my_alias, *}}}}}; // $ item=I1

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

Expand Down Expand Up @@ -816,6 +817,7 @@ fn main() {
nested8::f(); // $ item=I119
my3::f(); // $ item=I200
nested_f(); // $ item=I201
my_alias::nested_f(); // $ item=I201
m18::m19::m20::g(); // $ item=I103
m23::f(); // $ item=I108
m24::f(); // $ item=I121
Expand Down
Loading