Skip to content
Merged
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
101 changes: 80 additions & 21 deletions rust/ql/lib/codeql/rust/internal/PathResolution.qll
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@
}

pragma[nomagic]
private ItemNode getASuccessorRec(string name) {
ItemNode getASuccessorRec(string name) {
sourceFileEdge(this, name, result)
or
this = result.getImmediateParent() and
Expand Down Expand Up @@ -613,11 +613,11 @@
}

/**
* Holds if `m` is a `mod name;` module declaration happening in a file named
* `fileName.rs`, inside the folder `parent`.
* Holds if `m` is a `mod name;` module declaration, where the corresponding
* module file needs to be looked up in `lookup` or one of its descandants.
*/
private predicate modImport(Module m, string fileName, string name, Folder parent) {
exists(File f |
private predicate modImport0(Module m, string name, Folder lookup) {
exists(File f, Folder parent, string fileName |
f = m.getFile() and
not m.hasItemList() and
// TODO: handle
Expand All @@ -629,17 +629,63 @@
name = m.getName().getText() and
parent = f.getParentContainer() and
fileName = f.getStem()
|
// sibling import
lookup = parent and
(
m.getFile() = any(CrateItemNode c).getModuleNode().(SourceFileItemNode).getFile()
or
m.getFile().getBaseName() = "mod.rs"
)
or
// child import
lookup = parent.getFolder(fileName)
)
}

/**
* Holds if `m` is a `mod name;` module declaration, which happens inside a
* nested module, and `pred -> succ` is a module edge leading to `m`.
*/
private predicate modImportNested(ModuleItemNode m, ModuleItemNode pred, ModuleItemNode succ) {
pred.getAnItemInScope() = succ and
(
modImport0(m, _, _) and
succ = m
or
modImportNested(m, succ, _)
)
}

/**
* Holds if `m` is a `mod name;` module declaration, which happens inside a
* nested module, where `ancestor` is a reflexive transitive ancestor module
* of `m` with corresponding lookup folder `lookup`.
*/
private predicate modImportNestedLookup(Module m, ModuleItemNode ancestor, Folder lookup) {
modImport0(m, _, lookup) and
modImportNested(m, ancestor, _) and
not modImportNested(m, _, ancestor)
or
exists(ModuleItemNode m1, Folder mid |
modImportNestedLookup(m, m1, mid) and
modImportNested(m, m1, ancestor) and
lookup = mid.getFolder(m1.getName())
)
}

/** Holds if `m` is a `mod name;` item importing file `f`. */
private predicate fileImport(Module m, SourceFile f) {
exists(string fileName, string name, Folder parent | modImport(m, fileName, name, parent) |
// sibling import
exists(string name, Folder parent |
modImport0(m, name, _) and
fileModule(f, name, parent)
|
// `m` is not inside a nested module
modImport0(m, name, parent) and
not modImportNested(m, _, _)
or
// child import
fileModule(f, name, parent.getFolder(fileName))
// `m` is inside a nested module
modImportNestedLookup(m, m, parent)
)
}

Expand All @@ -651,7 +697,7 @@
private predicate fileImportEdge(Module mod, string name, ItemNode item) {
exists(SourceFileItemNode f |
fileImport(mod, f) and
item = f.getASuccessor(name)
item = f.getASuccessorRec(name)
)
}

Expand All @@ -660,7 +706,7 @@
*/
pragma[nomagic]
private predicate crateDefEdge(CrateItemNode c, string name, ItemNode i) {
i = c.getModuleNode().getASuccessor(name) and
i = c.getModuleNode().getASuccessorRec(name) and
not i instanceof Crate
}

Expand Down Expand Up @@ -742,7 +788,16 @@
// lookup in an outer scope, but only if the item is not declared in inner scope
exists(ItemNode mid |
unqualifiedPathLookup(p, name, ns, mid) and
not declares(mid, ns, name)
not declares(mid, ns, name) and
not name = ["super", "self"] and
not (
name = "Self" and
mid = any(ImplOrTraitItemNode i).getAnItemInSelfScope()
) and
not (
name = "crate" and
mid = any(CrateItemNode i).getASourceFile()
)
|
// nested modules do not have unqualified access to items from outer modules,
// except for items declared at top-level in the source file
Expand Down Expand Up @@ -906,7 +961,7 @@
mid = resolveUseTreeListItem(use, midTree) and
tree = midTree.getUseTreeList().getAUseTree() and
isUseTreeSubPathUnqualified(tree, path, pragma[only_bind_into](name)) and
result = mid.getASuccessor(pragma[only_bind_into](name))

Check warning

Code scanning / CodeQL

Dead code Warning

This code is never used, and it's not publicly exported.
)
or
exists(ItemNode q, string name |
Expand Down Expand Up @@ -943,15 +998,19 @@
encl.getADescendant() = use and
item = getASuccessor(used, name, ns) and
// glob imports can be shadowed
not declares(encl, ns, name)
not declares(encl, ns, name) and
not name = ["super", "self", "Self", "crate"]
)
else item = used
|
not tree.hasRename() and
name = item.getName()
or
name = tree.getRename().getName().getText() and
name != "_"
else (
item = used and
(
not tree.hasRename() and
name = item.getName()
or
name = tree.getRename().getName().getText() and
name != "_"
)
)
)
}

Expand All @@ -961,7 +1020,7 @@
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
filepath.matches("%/main.rs") and
startline = 1
startline = [1, 3]
)
}

Expand Down
22 changes: 22 additions & 0 deletions rust/ql/test/library-tests/path-resolution/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,26 @@ mod m17 {
} // I99
}

mod m18 {
fn f() {
println!("m18::f");
} // I101

pub mod m19 {
fn f() {
println!("m18::m19::f");
} // I102

pub mod m20 {
pub fn g() {
println!("m18::m19::m20::g");
super::f(); // $ item=I102
super::super::f(); // $ item=I101
} // I103
}
}
}

fn main() {
my::nested::nested1::nested2::f(); // $ item=I4
my::f(); // $ item=I38
Expand All @@ -498,4 +518,6 @@ fn main() {
nested6::f(); // $ item=I116
nested8::f(); // $ item=I119
my3::f(); // $ item=I200
nested_f(); // $ item=I201
m18::m19::m20::g(); // $ item=I103
}
6 changes: 6 additions & 0 deletions rust/ql/test/library-tests/path-resolution/my.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,9 @@ pub fn h() {
println!("my.rs::h");
g(); // $ item=I7
} // I39

mod my4 {
pub mod my5;
}

pub use my4::my5::f as nested_f; // $ item=I201
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub fn f() {
println!("my/my4/my5/mod.rs::f");
} // I201
126 changes: 72 additions & 54 deletions rust/ql/test/library-tests/path-resolution/path-resolution.expected
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ mod
| main.rs:294:1:348:1 | mod m15 |
| main.rs:350:1:442:1 | mod m16 |
| main.rs:444:1:474:1 | mod m17 |
| main.rs:476:1:494:1 | mod m18 |
| main.rs:481:5:493:5 | mod m19 |
| main.rs:486:9:492:9 | mod m20 |
| my2/mod.rs:1:1:1:16 | mod nested2 |
| my2/mod.rs:12:1:12:12 | mod my3 |
| my2/nested2.rs:1:1:11:1 | mod nested3 |
Expand All @@ -30,6 +33,8 @@ mod
| my2/nested2.rs:21:1:27:1 | mod nested7 |
| my2/nested2.rs:22:5:26:5 | mod nested8 |
| my.rs:1:1:1:15 | mod nested |
| my.rs:14:1:16:1 | mod my4 |
| my.rs:15:5:15:16 | mod my5 |
| my/nested.rs:1:1:17:1 | mod nested1 |
| my/nested.rs:2:5:11:5 | mod nested2 |
resolvePath
Expand All @@ -51,7 +56,7 @@ resolvePath
| main.rs:30:17:30:21 | super | main.rs:18:5:36:5 | mod m2 |
| main.rs:30:17:30:24 | ...::f | main.rs:19:9:21:9 | fn f |
| main.rs:33:17:33:17 | f | main.rs:19:9:21:9 | fn f |
| main.rs:40:9:40:13 | super | main.rs:1:1:501:2 | SourceFile |
| main.rs:40:9:40:13 | super | main.rs:1:1:523:2 | SourceFile |
| main.rs:40:9:40:17 | ...::m1 | main.rs:13:1:37:1 | mod m1 |
| main.rs:40:9:40:21 | ...::m2 | main.rs:18:5:36:5 | mod m2 |
| main.rs:40:9:40:24 | ...::g | main.rs:23:9:27:9 | fn g |
Expand All @@ -63,7 +68,7 @@ resolvePath
| main.rs:61:17:61:19 | Foo | main.rs:59:9:59:21 | struct Foo |
| main.rs:64:13:64:15 | Foo | main.rs:53:5:53:17 | struct Foo |
| main.rs:66:5:66:5 | f | main.rs:55:5:62:5 | fn f |
| main.rs:68:5:68:8 | self | main.rs:1:1:501:2 | SourceFile |
| main.rs:68:5:68:8 | self | main.rs:1:1:523:2 | SourceFile |
| main.rs:68:5:68:11 | ...::i | main.rs:71:1:83:1 | fn i |
| main.rs:74:13:74:15 | Foo | main.rs:48:1:48:13 | struct Foo |
| main.rs:81:17:81:19 | Foo | main.rs:77:9:79:9 | struct Foo |
Expand All @@ -77,7 +82,7 @@ resolvePath
| main.rs:87:57:87:66 | ...::g | my2/nested2.rs:7:9:9:9 | fn g |
| main.rs:87:80:87:86 | nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 |
| main.rs:100:5:100:22 | f_defined_in_macro | main.rs:99:18:99:42 | fn f_defined_in_macro |
| main.rs:117:13:117:17 | super | main.rs:1:1:501:2 | SourceFile |
| main.rs:117:13:117:17 | super | main.rs:1:1:523:2 | SourceFile |
| main.rs:117:13:117:21 | ...::m5 | main.rs:103:1:107:1 | mod m5 |
| main.rs:118:9:118:9 | f | main.rs:104:5:106:5 | fn f |
| main.rs:118:9:118:9 | f | main.rs:110:5:112:5 | fn f |
Expand Down Expand Up @@ -210,56 +215,66 @@ resolvePath
| main.rs:465:9:465:18 | ...::f | main.rs:446:9:446:20 | fn f |
| main.rs:470:9:470:9 | g | main.rs:459:5:466:5 | fn g |
| main.rs:471:11:471:11 | S | main.rs:449:5:449:13 | struct S |
| main.rs:477:5:477:6 | my | main.rs:1:1:1:7 | mod my |
| main.rs:477:5:477:14 | ...::nested | my.rs:1:1:1:15 | mod nested |
| main.rs:477:5:477:23 | ...::nested1 | my/nested.rs:1:1:17:1 | mod nested1 |
| main.rs:477:5:477:32 | ...::nested2 | my/nested.rs:2:5:11:5 | mod nested2 |
| main.rs:477:5:477:35 | ...::f | my/nested.rs:3:9:5:9 | fn f |
| main.rs:478:5:478:6 | my | main.rs:1:1:1:7 | mod my |
| main.rs:478:5:478:9 | ...::f | my.rs:5:1:7:1 | fn f |
| main.rs:479:5:479:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 |
| main.rs:479:5:479:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 |
| main.rs:479:5:479:29 | ...::nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 |
| main.rs:479:5:479:32 | ...::f | my2/nested2.rs:3:9:5:9 | fn f |
| main.rs:480:5:480:5 | f | my2/nested2.rs:3:9:5:9 | fn f |
| main.rs:481:5:481:5 | g | my2/nested2.rs:7:9:9:9 | fn g |
| main.rs:482:5:482:9 | crate | main.rs:0:0:0:0 | Crate(main@0.0.1) |
| main.rs:482:5:482:12 | ...::h | main.rs:50:1:69:1 | fn h |
| main.rs:483:5:483:6 | m1 | main.rs:13:1:37:1 | mod m1 |
| main.rs:483:5:483:10 | ...::m2 | main.rs:18:5:36:5 | mod m2 |
| main.rs:483:5:483:13 | ...::g | main.rs:23:9:27:9 | fn g |
| main.rs:484:5:484:6 | m1 | main.rs:13:1:37:1 | mod m1 |
| main.rs:484:5:484:10 | ...::m2 | main.rs:18:5:36:5 | mod m2 |
| main.rs:484:5:484:14 | ...::m3 | main.rs:29:9:35:9 | mod m3 |
| main.rs:484:5:484:17 | ...::h | main.rs:30:27:34:13 | fn h |
| main.rs:485:5:485:6 | m4 | main.rs:39:1:46:1 | mod m4 |
| main.rs:485:5:485:9 | ...::i | main.rs:42:5:45:5 | fn i |
| main.rs:486:5:486:5 | h | main.rs:50:1:69:1 | fn h |
| main.rs:487:5:487:11 | f_alias | my2/nested2.rs:3:9:5:9 | fn f |
| main.rs:488:5:488:11 | g_alias | my2/nested2.rs:7:9:9:9 | fn g |
| main.rs:489:5:489:5 | j | main.rs:97:1:101:1 | fn j |
| main.rs:490:5:490:6 | m6 | main.rs:109:1:120:1 | mod m6 |
| main.rs:490:5:490:9 | ...::g | main.rs:114:5:119:5 | fn g |
| main.rs:491:5:491:6 | m7 | main.rs:122:1:137:1 | mod m7 |
| main.rs:491:5:491:9 | ...::f | main.rs:129:5:136:5 | fn f |
| main.rs:492:5:492:6 | m8 | main.rs:139:1:193:1 | mod m8 |
| main.rs:492:5:492:9 | ...::g | main.rs:177:5:192:5 | fn g |
| main.rs:493:5:493:6 | m9 | main.rs:195:1:203:1 | mod m9 |
| main.rs:493:5:493:9 | ...::f | main.rs:198:5:202:5 | fn f |
| main.rs:494:5:494:7 | m11 | main.rs:226:1:263:1 | mod m11 |
| main.rs:494:5:494:10 | ...::f | main.rs:231:5:234:5 | fn f |
| main.rs:495:5:495:7 | m15 | main.rs:294:1:348:1 | mod m15 |
| main.rs:495:5:495:10 | ...::f | main.rs:335:5:347:5 | fn f |
| main.rs:496:5:496:7 | m16 | main.rs:350:1:442:1 | mod m16 |
| main.rs:496:5:496:10 | ...::f | main.rs:417:5:441:5 | fn f |
| main.rs:497:5:497:7 | m17 | main.rs:444:1:474:1 | mod m17 |
| main.rs:497:5:497:10 | ...::f | main.rs:468:5:473:5 | fn f |
| main.rs:498:5:498:11 | nested6 | my2/nested2.rs:14:5:18:5 | mod nested6 |
| main.rs:498:5:498:14 | ...::f | my2/nested2.rs:15:9:17:9 | fn f |
| main.rs:499:5:499:11 | nested8 | my2/nested2.rs:22:5:26:5 | mod nested8 |
| main.rs:499:5:499:14 | ...::f | my2/nested2.rs:23:9:25:9 | fn f |
| main.rs:500:5:500:7 | my3 | my2/mod.rs:12:1:12:12 | mod my3 |
| main.rs:500:5:500:10 | ...::f | my2/my3/mod.rs:1:1:5:1 | fn f |
| main.rs:489:17:489:21 | super | main.rs:481:5:493:5 | mod m19 |
| main.rs:489:17:489:24 | ...::f | main.rs:482:9:484:9 | fn f |
| main.rs:490:17:490:21 | super | main.rs:481:5:493:5 | mod m19 |
| main.rs:490:17:490:28 | ...::super | main.rs:476:1:494:1 | mod m18 |
| main.rs:490:17:490:31 | ...::f | main.rs:477:5:479:5 | fn f |
| main.rs:497:5:497:6 | my | main.rs:1:1:1:7 | mod my |
| main.rs:497:5:497:14 | ...::nested | my.rs:1:1:1:15 | mod nested |
| main.rs:497:5:497:23 | ...::nested1 | my/nested.rs:1:1:17:1 | mod nested1 |
| main.rs:497:5:497:32 | ...::nested2 | my/nested.rs:2:5:11:5 | mod nested2 |
| main.rs:497:5:497:35 | ...::f | my/nested.rs:3:9:5:9 | fn f |
| main.rs:498:5:498:6 | my | main.rs:1:1:1:7 | mod my |
| main.rs:498:5:498:9 | ...::f | my.rs:5:1:7:1 | fn f |
| main.rs:499:5:499:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 |
| main.rs:499:5:499:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 |
| main.rs:499:5:499:29 | ...::nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 |
| main.rs:499:5:499:32 | ...::f | my2/nested2.rs:3:9:5:9 | fn f |
| main.rs:500:5:500:5 | f | my2/nested2.rs:3:9:5:9 | fn f |
| main.rs:501:5:501:5 | g | my2/nested2.rs:7:9:9:9 | fn g |
| main.rs:502:5:502:9 | crate | main.rs:0:0:0:0 | Crate(main@0.0.1) |
| main.rs:502:5:502:12 | ...::h | main.rs:50:1:69:1 | fn h |
| main.rs:503:5:503:6 | m1 | main.rs:13:1:37:1 | mod m1 |
| main.rs:503:5:503:10 | ...::m2 | main.rs:18:5:36:5 | mod m2 |
| main.rs:503:5:503:13 | ...::g | main.rs:23:9:27:9 | fn g |
| main.rs:504:5:504:6 | m1 | main.rs:13:1:37:1 | mod m1 |
| main.rs:504:5:504:10 | ...::m2 | main.rs:18:5:36:5 | mod m2 |
| main.rs:504:5:504:14 | ...::m3 | main.rs:29:9:35:9 | mod m3 |
| main.rs:504:5:504:17 | ...::h | main.rs:30:27:34:13 | fn h |
| main.rs:505:5:505:6 | m4 | main.rs:39:1:46:1 | mod m4 |
| main.rs:505:5:505:9 | ...::i | main.rs:42:5:45:5 | fn i |
| main.rs:506:5:506:5 | h | main.rs:50:1:69:1 | fn h |
| main.rs:507:5:507:11 | f_alias | my2/nested2.rs:3:9:5:9 | fn f |
| main.rs:508:5:508:11 | g_alias | my2/nested2.rs:7:9:9:9 | fn g |
| main.rs:509:5:509:5 | j | main.rs:97:1:101:1 | fn j |
| main.rs:510:5:510:6 | m6 | main.rs:109:1:120:1 | mod m6 |
| main.rs:510:5:510:9 | ...::g | main.rs:114:5:119:5 | fn g |
| main.rs:511:5:511:6 | m7 | main.rs:122:1:137:1 | mod m7 |
| main.rs:511:5:511:9 | ...::f | main.rs:129:5:136:5 | fn f |
| main.rs:512:5:512:6 | m8 | main.rs:139:1:193:1 | mod m8 |
| main.rs:512:5:512:9 | ...::g | main.rs:177:5:192:5 | fn g |
| main.rs:513:5:513:6 | m9 | main.rs:195:1:203:1 | mod m9 |
| main.rs:513:5:513:9 | ...::f | main.rs:198:5:202:5 | fn f |
| main.rs:514:5:514:7 | m11 | main.rs:226:1:263:1 | mod m11 |
| main.rs:514:5:514:10 | ...::f | main.rs:231:5:234:5 | fn f |
| main.rs:515:5:515:7 | m15 | main.rs:294:1:348:1 | mod m15 |
| main.rs:515:5:515:10 | ...::f | main.rs:335:5:347:5 | fn f |
| main.rs:516:5:516:7 | m16 | main.rs:350:1:442:1 | mod m16 |
| main.rs:516:5:516:10 | ...::f | main.rs:417:5:441:5 | fn f |
| main.rs:517:5:517:7 | m17 | main.rs:444:1:474:1 | mod m17 |
| main.rs:517:5:517:10 | ...::f | main.rs:468:5:473:5 | fn f |
| main.rs:518:5:518:11 | nested6 | my2/nested2.rs:14:5:18:5 | mod nested6 |
| main.rs:518:5:518:14 | ...::f | my2/nested2.rs:15:9:17:9 | fn f |
| main.rs:519:5:519:11 | nested8 | my2/nested2.rs:22:5:26:5 | mod nested8 |
| main.rs:519:5:519:14 | ...::f | my2/nested2.rs:23:9:25:9 | fn f |
| main.rs:520:5:520:7 | my3 | my2/mod.rs:12:1:12:12 | mod my3 |
| main.rs:520:5:520:10 | ...::f | my2/my3/mod.rs:1:1:5:1 | fn f |
| main.rs:521:5:521:12 | nested_f | my/my4/my5/mod.rs:1:1:3:1 | fn f |
| main.rs:522:5:522:7 | m18 | main.rs:476:1:494:1 | mod m18 |
| main.rs:522:5:522:12 | ...::m19 | main.rs:481:5:493:5 | mod m19 |
| main.rs:522:5:522:17 | ...::m20 | main.rs:486:9:492:9 | mod m20 |
| main.rs:522:5:522:20 | ...::g | main.rs:487:13:491:13 | fn g |
| my2/mod.rs:5:5:5:11 | nested2 | my2/mod.rs:1:1:1:16 | mod nested2 |
| my2/mod.rs:5:5:5:20 | ...::nested3 | my2/nested2.rs:1:1:11:1 | mod nested3 |
| my2/mod.rs:5:5:5:29 | ...::nested4 | my2/nested2.rs:2:5:10:5 | mod nested4 |
Expand All @@ -273,13 +288,16 @@ resolvePath
| my2/my3/mod.rs:3:5:3:5 | g | my2/mod.rs:3:1:6:1 | fn g |
| my2/my3/mod.rs:4:5:4:5 | h | main.rs:50:1:69:1 | fn h |
| my2/my3/mod.rs:7:5:7:9 | super | my2/mod.rs:1:1:12:13 | SourceFile |
| my2/my3/mod.rs:7:5:7:16 | ...::super | main.rs:1:1:501:2 | SourceFile |
| my2/my3/mod.rs:7:5:7:16 | ...::super | main.rs:1:1:523:2 | SourceFile |
| my2/my3/mod.rs:7:5:7:19 | ...::h | main.rs:50:1:69:1 | fn h |
| my2/my3/mod.rs:8:5:8:9 | super | my2/mod.rs:1:1:12:13 | SourceFile |
| my2/my3/mod.rs:8:5:8:12 | ...::g | my2/mod.rs:3:1:6:1 | fn g |
| my.rs:3:5:3:10 | nested | my.rs:1:1:1:15 | mod nested |
| my.rs:3:5:3:13 | ...::g | my/nested.rs:19:1:22:1 | fn g |
| my.rs:11:5:11:5 | g | my/nested.rs:19:1:22:1 | fn g |
| my.rs:18:9:18:11 | my4 | my.rs:14:1:16:1 | mod my4 |
| my.rs:18:9:18:16 | ...::my5 | my.rs:15:5:15:16 | mod my5 |
| my.rs:18:9:18:19 | ...::f | my/my4/my5/mod.rs:1:1:3:1 | fn f |
| my/nested.rs:9:13:9:13 | f | my/nested.rs:3:9:5:9 | fn f |
| my/nested.rs:15:9:15:15 | nested2 | my/nested.rs:2:5:11:5 | mod nested2 |
| my/nested.rs:15:9:15:18 | ...::f | my/nested.rs:3:9:5:9 | fn f |
Expand Down