diff --git a/rust/ql/lib/codeql/rust/internal/PathResolution.qll b/rust/ql/lib/codeql/rust/internal/PathResolution.qll index a2203d199d1..ad3595e3e17 100644 --- a/rust/ql/lib/codeql/rust/internal/PathResolution.qll +++ b/rust/ql/lib/codeql/rust/internal/PathResolution.qll @@ -226,6 +226,8 @@ private class SourceFileItemNode extends ModuleLikeNode, SourceFile { override Visibility getVisibility() { none() } + override predicate isPublic() { any() } + override TypeParam getTypeParam(int i) { none() } } @@ -271,6 +273,8 @@ class CrateItemNode extends ItemNode instanceof Crate { override Visibility getVisibility() { none() } + override predicate isPublic() { any() } + override TypeParam getTypeParam(int i) { none() } } @@ -648,7 +652,6 @@ private predicate fileImport(Module m, SourceFile f) { */ pragma[nomagic] private predicate fileImportEdge(Module mod, string name, ItemNode item) { - item.isPublic() and exists(SourceFileItemNode f | fileImport(mod, f) and item = f.getASuccessor(name) @@ -828,9 +831,8 @@ private predicate pathUsesNamespace(Path p, Namespace n) { ) } -/** Gets the item that `path` resolves to, if any. */ -cached -ItemNode resolvePath(RelevantPath path) { +pragma[nomagic] +private ItemNode resolvePath1(RelevantPath path) { exists(Namespace ns | result = resolvePath0(path, ns) | pathUsesNamespace(path, ns) or @@ -839,6 +841,47 @@ ItemNode resolvePath(RelevantPath path) { ) } +pragma[nomagic] +private ItemNode resolvePathPrivate( + RelevantPath path, ModuleLikeNode itemParent, ModuleLikeNode pathParent +) { + result = resolvePath1(path) and + itemParent = result.getImmediateParentModule() and + not result.isPublic() and + ( + pathParent.getADescendant() = path + or + pathParent = any(ItemNode mid | path = mid.getADescendant()).getImmediateParentModule() + ) +} + +/** + * Gets a module that has access to private items defined inside `itemParent`. + * + * According to + * + * 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 + * + * this is either `itemParent` itself or any (transitive) child of `itemParent`. + */ +pragma[nomagic] +private ModuleLikeNode getAPrivateVisibleModule(ModuleLikeNode itemParent) { + exists(resolvePathPrivate(_, itemParent, _)) and + result.getImmediateParentModule*() = itemParent +} + +/** Gets the item that `path` resolves to, if any. */ +cached +ItemNode resolvePath(RelevantPath path) { + result = resolvePath1(path) and + result.isPublic() + or + exists(ModuleLikeNode itemParent, ModuleLikeNode pathParent | + result = resolvePathPrivate(path, itemParent, pathParent) and + pathParent = getAPrivateVisibleModule(itemParent) + ) +} + pragma[nomagic] private ItemNode resolvePathQualifier(RelevantPath path, string name) { result = resolvePath(path.getQualifier()) and