Skip to content

Commit f1ae6a3

Browse files
committed
Rust: Rework visibility handling in path resolution
1 parent fcc44a9 commit f1ae6a3

File tree

1 file changed

+48
-6
lines changed

1 file changed

+48
-6
lines changed

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

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ private class SourceFileItemNode extends ModuleLikeNode, SourceFile {
229229

230230
override Visibility getVisibility() { none() }
231231

232+
override predicate isPublic() { any() }
233+
232234
override TypeParam getTypeParam(int i) { none() }
233235
}
234236

@@ -274,6 +276,8 @@ class CrateItemNode extends ItemNode instanceof Crate {
274276

275277
override Visibility getVisibility() { none() }
276278

279+
override predicate isPublic() { any() }
280+
277281
override TypeParam getTypeParam(int i) { none() }
278282
}
279283

@@ -651,7 +655,6 @@ private predicate fileImport(Module m, SourceFile f) {
651655
*/
652656
pragma[nomagic]
653657
private predicate fileImportEdge(Module mod, string name, ItemNode item) {
654-
item.isPublic() and
655658
exists(SourceFileItemNode f |
656659
fileImport(mod, f) and
657660
item = f.getASuccessor(name)
@@ -663,8 +666,7 @@ private predicate fileImportEdge(Module mod, string name, ItemNode item) {
663666
*/
664667
pragma[nomagic]
665668
private predicate crateDefEdge(CrateItemNode c, string name, ItemNode i) {
666-
i = c.getModuleNode().getASuccessor(name) and
667-
i.isPublic()
669+
i = c.getModuleNode().getASuccessor(name)
668670
}
669671

670672
/**
@@ -831,9 +833,8 @@ private predicate pathUsesNamespace(Path p, Namespace n) {
831833
)
832834
}
833835

834-
/** Gets the item that `path` resolves to, if any. */
835-
cached
836-
ItemNode resolvePath(RelevantPath path) {
836+
pragma[nomagic]
837+
private ItemNode resolvePath1(RelevantPath path) {
837838
exists(Namespace ns | result = resolvePath0(path, ns) |
838839
pathUsesNamespace(path, ns)
839840
or
@@ -842,6 +843,47 @@ ItemNode resolvePath(RelevantPath path) {
842843
)
843844
}
844845

846+
pragma[nomagic]
847+
private ItemNode resolvePathPrivate(
848+
RelevantPath path, ModuleLikeNode itemParent, ModuleLikeNode pathParent
849+
) {
850+
result = resolvePath1(path) and
851+
itemParent = result.getImmediateParentModule() and
852+
not result.isPublic() and
853+
(
854+
pathParent.getADescendant() = path
855+
or
856+
pathParent = any(ItemNode mid | path = mid.getADescendant()).getImmediateParentModule()
857+
)
858+
}
859+
860+
/**
861+
* Gets a module that has access to private items defined inside `itemParent`.
862+
*
863+
* According to
864+
*
865+
* https://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/share/doc/rust/html/book/second-edition/ch07-02-controlling-visibility-with-pub.html#privacy-rules
866+
*
867+
* this is either `itemParent` itself or any (transitive) child of `itemParent`.
868+
*/
869+
pragma[nomagic]
870+
private ModuleLikeNode getAPrivateVisibleModule(ModuleLikeNode itemParent) {
871+
exists(resolvePathPrivate(_, itemParent, _)) and
872+
result.getImmediateParentModule*() = itemParent
873+
}
874+
875+
/** Gets the item that `path` resolves to, if any. */
876+
cached
877+
ItemNode resolvePath(RelevantPath path) {
878+
result = resolvePath1(path) and
879+
result.isPublic()
880+
or
881+
exists(ModuleLikeNode itemParent, ModuleLikeNode pathParent |
882+
result = resolvePathPrivate(path, itemParent, pathParent) and
883+
pathParent = getAPrivateVisibleModule(itemParent)
884+
)
885+
}
886+
845887
pragma[nomagic]
846888
private ItemNode resolvePathQualifier(RelevantPath path, string name) {
847889
result = resolvePath(path.getQualifier()) and

0 commit comments

Comments
 (0)