Skip to content

Commit f9255d3

Browse files
committed
Rust: Rework visibility handling in path resolution
1 parent 3542955 commit f9255d3

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
@@ -241,6 +241,8 @@ private class SourceFileItemNode extends ModuleLikeNode, SourceFile {
241241

242242
override Visibility getVisibility() { none() }
243243

244+
override predicate isPublic() { any() }
245+
244246
override TypeParam getTypeParam(int i) { none() }
245247
}
246248

@@ -286,6 +288,8 @@ class CrateItemNode extends ItemNode instanceof Crate {
286288

287289
override Visibility getVisibility() { none() }
288290

291+
override predicate isPublic() { any() }
292+
289293
override TypeParam getTypeParam(int i) { none() }
290294
}
291295

@@ -663,7 +667,6 @@ private predicate fileImport(Module m, SourceFile f) {
663667
*/
664668
pragma[nomagic]
665669
private predicate fileImportEdge(Module mod, string name, ItemNode item) {
666-
item.isPublic() and
667670
exists(SourceFileItemNode f |
668671
fileImport(mod, f) and
669672
item = f.getASuccessor(name)
@@ -675,8 +678,7 @@ private predicate fileImportEdge(Module mod, string name, ItemNode item) {
675678
*/
676679
pragma[nomagic]
677680
private predicate crateDefEdge(CrateItemNode c, string name, ItemNode i) {
678-
i = c.getModuleNode().getASuccessor(name) and
679-
i.isPublic()
681+
i = c.getModuleNode().getASuccessor(name)
680682
}
681683

682684
/**
@@ -837,9 +839,8 @@ private predicate pathUsesNamespace(Path p, Namespace n) {
837839
)
838840
}
839841

840-
/** Gets the item that `path` resolves to, if any. */
841-
cached
842-
ItemNode resolvePath(RelevantPath path) {
842+
pragma[nomagic]
843+
private ItemNode resolvePath1(RelevantPath path) {
843844
exists(Namespace ns | result = resolvePath0(path, ns) |
844845
pathUsesNamespace(path, ns)
845846
or
@@ -848,6 +849,47 @@ ItemNode resolvePath(RelevantPath path) {
848849
)
849850
}
850851

852+
pragma[nomagic]
853+
private ItemNode resolvePathPrivate(
854+
RelevantPath path, ModuleLikeNode itemParent, ModuleLikeNode pathParent
855+
) {
856+
result = resolvePath1(path) and
857+
itemParent = result.getImmediateParentModule() and
858+
not result.isPublic() and
859+
(
860+
pathParent.getADescendant() = path
861+
or
862+
pathParent = any(ItemNode mid | path = mid.getADescendant()).getImmediateParentModule()
863+
)
864+
}
865+
866+
/**
867+
* Gets a module that has access to private items defined inside `itemParent`.
868+
*
869+
* According to
870+
*
871+
* 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
872+
*
873+
* this is either `itemParent` itself or any (transitive) child of `itemParent`.
874+
*/
875+
pragma[nomagic]
876+
private ModuleLikeNode getAPrivateVisibleModule(ModuleLikeNode itemParent) {
877+
exists(resolvePathPrivate(_, itemParent, _)) and
878+
result.getImmediateParentModule*() = itemParent
879+
}
880+
881+
/** Gets the item that `path` resolves to, if any. */
882+
cached
883+
ItemNode resolvePath(RelevantPath path) {
884+
result = resolvePath1(path) and
885+
result.isPublic()
886+
or
887+
exists(ModuleLikeNode itemParent, ModuleLikeNode pathParent |
888+
result = resolvePathPrivate(path, itemParent, pathParent) and
889+
pathParent = getAPrivateVisibleModule(itemParent)
890+
)
891+
}
892+
851893
pragma[nomagic]
852894
private ItemNode resolvePathQualifier(RelevantPath path, string name) {
853895
result = resolvePath(path.getQualifier()) and

0 commit comments

Comments
 (0)