Skip to content

Commit edf359a

Browse files
committed
Rust: Also check visibility in method call resolution
1 parent 1b67b30 commit edf359a

3 files changed

Lines changed: 60 additions & 45 deletions

File tree

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

Lines changed: 53 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,7 +1112,7 @@ private predicate pathUsesNamespace(Path p, Namespace n) {
11121112
}
11131113

11141114
pragma[nomagic]
1115-
private ItemNode resolvePath1(RelevantPath path) {
1115+
private ItemNode resolvePathCand(AstNode path) {
11161116
exists(Namespace ns | result = resolvePath0(path, ns) |
11171117
pathUsesNamespace(path, ns)
11181118
or
@@ -1121,54 +1121,65 @@ private ItemNode resolvePath1(RelevantPath path) {
11211121
)
11221122
}
11231123

1124-
pragma[nomagic]
1125-
private ItemNode resolvePathPrivate(
1126-
RelevantPath path, ModuleLikeNode itemParent, ModuleLikeNode pathParent
1127-
) {
1128-
result = resolvePath1(path) and
1129-
result.isPrivate() and
1130-
(
1131-
pathParent.getADescendant() = path
1132-
or
1133-
pathParent = any(ItemNode mid | path = mid.getADescendant()).getImmediateParentModule()
1134-
) and
1135-
(
1136-
itemParent = result.getVisibilityParent().getImmediateParentModule()
1137-
or
1138-
not result.hasVisibilityParent() and
1139-
itemParent = result.getImmediateParentModule()
1140-
)
1141-
}
1124+
/** Gets an item that `n` may resolve to, not taking visibility into account. */
1125+
signature ItemNode resolveCandidateSig(AstNode n);
11421126

1143-
pragma[nomagic]
1144-
private predicate isItemParent(ModuleLikeNode itemParent) {
1145-
exists(resolvePathPrivate(_, itemParent, _))
1146-
}
1127+
/** Provides the predicate `resolve` for resolving items while taking visibility into account. */
1128+
module ResolveWithVisibility<resolveCandidateSig/1 resolvePrivateCandidate> {
1129+
pragma[nomagic]
1130+
private ItemNode resolvePathPrivate(
1131+
AstNode n, ModuleLikeNode itemParent, ModuleLikeNode pathParent
1132+
) {
1133+
result = resolvePrivateCandidate(n) and
1134+
result.isPrivate() and
1135+
(
1136+
pathParent.getADescendant() = n
1137+
or
1138+
pathParent = any(ItemNode mid | n = mid.getADescendant()).getImmediateParentModule()
1139+
) and
1140+
(
1141+
itemParent = result.getVisibilityParent().getImmediateParentModule()
1142+
or
1143+
not result.hasVisibilityParent() and
1144+
itemParent = result.getImmediateParentModule()
1145+
)
1146+
}
11471147

1148-
/**
1149-
* Gets a module that has access to private items defined inside `itemParent`.
1150-
*
1151-
* According to [The Rust Reference][1] this is either `itemParent` itself or any
1152-
* descendant of `itemParent`.
1153-
*
1154-
* [1]: https://doc.rust-lang.org/reference/visibility-and-privacy.html#r-vis.access
1155-
*/
1156-
pragma[nomagic]
1157-
private ModuleLikeNode getAPrivateVisibleModule(ModuleLikeNode itemParent) {
1158-
isItemParent(itemParent) and
1159-
result.getImmediateParentModule*() = itemParent
1148+
pragma[nomagic]
1149+
private predicate isItemParent(ModuleLikeNode itemParent) {
1150+
exists(resolvePathPrivate(_, itemParent, _))
1151+
}
1152+
1153+
/**
1154+
* Gets a module that has access to private items defined inside `itemParent`.
1155+
*
1156+
* According to [The Rust Reference][1] this is either `itemParent` itself or any
1157+
* descendant of `itemParent`.
1158+
*
1159+
* [1]: https://doc.rust-lang.org/reference/visibility-and-privacy.html#r-vis.access
1160+
*/
1161+
pragma[nomagic]
1162+
private ModuleLikeNode getAPrivateVisibleModule(ModuleLikeNode itemParent) {
1163+
isItemParent(itemParent) and
1164+
result.getImmediateParentModule*() = itemParent
1165+
}
1166+
1167+
/** Gets an item that `n` may resolve to, taking visibility into account. */
1168+
ItemNode resolve(AstNode n) {
1169+
result = resolvePrivateCandidate(n) and
1170+
result.isPublic()
1171+
or
1172+
exists(ModuleLikeNode itemParent, ModuleLikeNode pathParent |
1173+
result = resolvePathPrivate(n, itemParent, pathParent) and
1174+
pathParent = getAPrivateVisibleModule(itemParent)
1175+
)
1176+
}
11601177
}
11611178

11621179
/** Gets the item that `path` resolves to, if any. */
11631180
cached
11641181
ItemNode resolvePath(RelevantPath path) {
1165-
result = resolvePath1(path) and
1166-
result.isPublic()
1167-
or
1168-
exists(ModuleLikeNode itemParent, ModuleLikeNode pathParent |
1169-
result = resolvePathPrivate(path, itemParent, pathParent) and
1170-
pathParent = getAPrivateVisibleModule(itemParent)
1171-
)
1182+
result = ResolveWithVisibility<resolvePathCand/1>::resolve(path)
11721183
}
11731184

11741185
pragma[nomagic]

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -913,12 +913,16 @@ private module Cached {
913913
name = mce.getIdentifier().getText()
914914
}
915915

916+
private ItemNode resolveMethodCallExprCand(AstNode mce) {
917+
exists(string name | result = getMethodCallExprLookupType(mce, name).getMethod(name))
918+
}
919+
916920
/**
917921
* Gets a method that the method call `mce` resolves to, if any.
918922
*/
919923
cached
920924
Function resolveMethodCallExpr(MethodCallExpr mce) {
921-
exists(string name | result = getMethodCallExprLookupType(mce, name).getMethod(name))
925+
result = ResolveWithVisibility<resolveMethodCallExprCand/1>::resolve(mce)
922926
}
923927

924928
pragma[nomagic]

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ mod m1 {
4747
pub fn f() {
4848
println!("m1::nested2::f");
4949
super::S(). // $ item=I1
50-
f(); // $ SPURIOUS: item=I4 (private)
50+
f(); // illegal: private
5151
super::S::f( // illegal: private
5252
super::S() // $ item=I1
5353
);
@@ -62,7 +62,7 @@ mod m1 {
6262
super::S() // $ item=I1
6363
);
6464
super::S(). // $ item=I1
65-
f2(); // $ SPURIOUS: item=I7 (private)
65+
f2(); // illegal: private
6666
super::S::f2(
6767
super::S() // $ item=I1
6868
); // illegal: private

0 commit comments

Comments
 (0)