Skip to content

Commit 73193d6

Browse files
committed
Rust: More path resolution improvements
1 parent f6ac82a commit 73193d6

4 files changed

Lines changed: 75 additions & 24 deletions

File tree

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

Lines changed: 71 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ abstract class ItemNode extends Locatable {
116116
}
117117

118118
pragma[nomagic]
119-
private ItemNode getASuccessorRec(string name) {
119+
ItemNode getASuccessorRec(string name) {
120120
sourceFileEdge(this, name, result)
121121
or
122122
this = result.getImmediateParent() and
@@ -613,11 +613,11 @@ private predicate fileModule(SourceFile f, string name, Folder folder) {
613613
}
614614

615615
/**
616-
* Holds if `m` is a `mod name;` module declaration happening in a file named
617-
* `fileName.rs`, inside the folder `parent`.
616+
* Holds if `m` is a `mod name;` module declaration, where the corresponding
617+
* module file needs to be looked up in `lookup` or one of its descandants.
618618
*/
619-
private predicate modImport(Module m, string fileName, string name, Folder parent) {
620-
exists(File f |
619+
private predicate modImport0(Module m, string name, Folder lookup) {
620+
exists(File f, Folder parent, string fileName |
621621
f = m.getFile() and
622622
not m.hasItemList() and
623623
// TODO: handle
@@ -629,17 +629,53 @@ private predicate modImport(Module m, string fileName, string name, Folder paren
629629
name = m.getName().getText() and
630630
parent = f.getParentContainer() and
631631
fileName = f.getStem()
632+
|
633+
// sibling import
634+
lookup = parent and
635+
(
636+
m.getFile() = any(CrateItemNode c).getModuleNode().(SourceFileItemNode).getFile()
637+
or
638+
m.getFile().getBaseName() = "mod.rs"
639+
)
640+
or
641+
// child import
642+
lookup = parent.getFolder(fileName)
643+
)
644+
}
645+
646+
private predicate modImportNestEdge(ModuleItemNode m, ModuleItemNode pred, ModuleItemNode succ) {
647+
pred.getAnItemInScope() = succ and
648+
(
649+
modImport0(m, _, _) and
650+
succ = m
651+
or
652+
modImportNestEdge(m, succ, _)
653+
)
654+
}
655+
656+
private predicate modImport1(Module m, ModuleItemNode m0, Folder parent) {
657+
modImport0(m, _, parent) and
658+
(
659+
m = m0 and
660+
not modImportNestEdge(m, _, _)
661+
or
662+
modImportNestEdge(m, m0, _) and
663+
not modImportNestEdge(m, _, m0)
664+
)
665+
or
666+
exists(ModuleItemNode m1, Folder mid |
667+
modImport1(m, m1, mid) and
668+
modImportNestEdge(m, m1, m0) and
669+
parent = mid.getFolder(m1.getName())
632670
)
633671
}
634672

635673
/** Holds if `m` is a `mod name;` item importing file `f`. */
636674
private predicate fileImport(Module m, SourceFile f) {
637-
exists(string fileName, string name, Folder parent | modImport(m, fileName, name, parent) |
638-
// sibling import
675+
exists(string name, Folder parent |
676+
modImport0(m, name, _) and
677+
modImport1(m, m, parent) and
639678
fileModule(f, name, parent)
640-
or
641-
// child import
642-
fileModule(f, name, parent.getFolder(fileName))
643679
)
644680
}
645681

@@ -651,7 +687,7 @@ pragma[nomagic]
651687
private predicate fileImportEdge(Module mod, string name, ItemNode item) {
652688
exists(SourceFileItemNode f |
653689
fileImport(mod, f) and
654-
item = f.getASuccessor(name)
690+
item = f.getASuccessorRec(name)
655691
)
656692
}
657693

@@ -660,7 +696,7 @@ private predicate fileImportEdge(Module mod, string name, ItemNode item) {
660696
*/
661697
pragma[nomagic]
662698
private predicate crateDefEdge(CrateItemNode c, string name, ItemNode i) {
663-
i = c.getModuleNode().getASuccessor(name) and
699+
i = c.getModuleNode().getASuccessorRec(name) and
664700
not i instanceof Crate
665701
}
666702

@@ -742,7 +778,16 @@ private predicate unqualifiedPathLookup(RelevantPath p, string name, Namespace n
742778
// lookup in an outer scope, but only if the item is not declared in inner scope
743779
exists(ItemNode mid |
744780
unqualifiedPathLookup(p, name, ns, mid) and
745-
not declares(mid, ns, name)
781+
not declares(mid, ns, name) and
782+
not name = ["super", "self"] and
783+
not (
784+
name = "Self" and
785+
mid = any(ImplOrTraitItemNode i).getAnItemInSelfScope()
786+
) and
787+
not (
788+
name = "crate" and
789+
mid = any(CrateItemNode i).getASourceFile()
790+
)
746791
|
747792
// nested modules do not have unqualified access to items from outer modules,
748793
// except for items declared at top-level in the source file
@@ -943,15 +988,19 @@ private predicate useImportEdge(Use use, string name, ItemNode item) {
943988
encl.getADescendant() = use and
944989
item = getASuccessor(used, name, ns) and
945990
// glob imports can be shadowed
946-
not declares(encl, ns, name)
991+
not declares(encl, ns, name) and
992+
not name = ["super", "self", "Self", "crate"]
947993
)
948-
else item = used
949-
|
950-
not tree.hasRename() and
951-
name = item.getName()
952-
or
953-
name = tree.getRename().getName().getText() and
954-
name != "_"
994+
else (
995+
item = used and
996+
(
997+
not tree.hasRename() and
998+
name = item.getName()
999+
or
1000+
name = tree.getRename().getName().getText() and
1001+
name != "_"
1002+
)
1003+
)
9551004
)
9561005
}
9571006

@@ -961,7 +1010,7 @@ private module Debug {
9611010
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
9621011
result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
9631012
filepath.matches("%/main.rs") and
964-
startline = 1
1013+
startline = [1, 3]
9651014
)
9661015
}
9671016

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,6 @@ fn main() {
518518
nested6::f(); // $ item=I116
519519
nested8::f(); // $ item=I119
520520
my3::f(); // $ item=I200
521-
nested_f(); // $ MISSING: item=I201
521+
nested_f(); // $ item=I201
522522
m18::m19::m20::g(); // $ item=I103
523523
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ mod my4 {
1515
pub mod my5;
1616
}
1717

18-
pub use my4::my5::f as nested_f; // $ MISSING: item=I201
18+
pub use my4::my5::f as nested_f; // $ item=I201

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ resolvePath
270270
| main.rs:519:5:519:14 | ...::f | my2/nested2.rs:23:9:25:9 | fn f |
271271
| main.rs:520:5:520:7 | my3 | my2/mod.rs:12:1:12:12 | mod my3 |
272272
| main.rs:520:5:520:10 | ...::f | my2/my3/mod.rs:1:1:5:1 | fn f |
273+
| main.rs:521:5:521:12 | nested_f | my/my4/my5/mod.rs:1:1:3:1 | fn f |
273274
| main.rs:522:5:522:7 | m18 | main.rs:476:1:494:1 | mod m18 |
274275
| main.rs:522:5:522:12 | ...::m19 | main.rs:481:5:493:5 | mod m19 |
275276
| main.rs:522:5:522:17 | ...::m20 | main.rs:486:9:492:9 | mod m20 |
@@ -296,6 +297,7 @@ resolvePath
296297
| my.rs:11:5:11:5 | g | my/nested.rs:19:1:22:1 | fn g |
297298
| my.rs:18:9:18:11 | my4 | my.rs:14:1:16:1 | mod my4 |
298299
| my.rs:18:9:18:16 | ...::my5 | my.rs:15:5:15:16 | mod my5 |
300+
| my.rs:18:9:18:19 | ...::f | my/my4/my5/mod.rs:1:1:3:1 | fn f |
299301
| my/nested.rs:9:13:9:13 | f | my/nested.rs:3:9:5:9 | fn f |
300302
| my/nested.rs:15:9:15:15 | nested2 | my/nested.rs:2:5:11:5 | mod nested2 |
301303
| my/nested.rs:15:9:15:18 | ...::f | my/nested.rs:3:9:5:9 | fn f |

0 commit comments

Comments
 (0)