Skip to content

Commit 3142dbb

Browse files
committed
Rust: Rework visibility handling in path resolution
1 parent b2fc7e7 commit 3142dbb

File tree

1 file changed

+47
-4
lines changed

1 file changed

+47
-4
lines changed

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

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ private class SourceFileItemNode extends ModuleLikeNode, SourceFile {
226226

227227
override Visibility getVisibility() { none() }
228228

229+
override predicate isPublic() { any() }
230+
229231
override TypeParam getTypeParam(int i) { none() }
230232
}
231233

@@ -271,6 +273,8 @@ class CrateItemNode extends ItemNode instanceof Crate {
271273

272274
override Visibility getVisibility() { none() }
273275

276+
override predicate isPublic() { any() }
277+
274278
override TypeParam getTypeParam(int i) { none() }
275279
}
276280

@@ -648,7 +652,6 @@ private predicate fileImport(Module m, SourceFile f) {
648652
*/
649653
pragma[nomagic]
650654
private predicate fileImportEdge(Module mod, string name, ItemNode item) {
651-
item.isPublic() and
652655
exists(SourceFileItemNode f |
653656
fileImport(mod, f) and
654657
item = f.getASuccessor(name)
@@ -828,9 +831,8 @@ private predicate pathUsesNamespace(Path p, Namespace n) {
828831
)
829832
}
830833

831-
/** Gets the item that `path` resolves to, if any. */
832-
cached
833-
ItemNode resolvePath(RelevantPath path) {
834+
pragma[nomagic]
835+
private ItemNode resolvePath1(RelevantPath path) {
834836
exists(Namespace ns | result = resolvePath0(path, ns) |
835837
pathUsesNamespace(path, ns)
836838
or
@@ -839,6 +841,47 @@ ItemNode resolvePath(RelevantPath path) {
839841
)
840842
}
841843

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

0 commit comments

Comments
 (0)