Skip to content

Commit 4ef18ca

Browse files
committed
Rust: Also check visibility in method call resolution
1 parent e7aa3cb commit 4ef18ca

File tree

3 files changed

+65
-50
lines changed

3 files changed

+65
-50
lines changed

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

Lines changed: 58 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,7 +1153,7 @@ private predicate pathUsesNamespace(Path p, Namespace n) {
11531153
}
11541154

11551155
pragma[nomagic]
1156-
private ItemNode resolvePath1(RelevantPath path) {
1156+
private ItemNode resolvePathCand(AstNode path) {
11571157
exists(Namespace ns | result = resolvePath0(path, ns) |
11581158
pathUsesNamespace(path, ns)
11591159
or
@@ -1162,59 +1162,70 @@ private ItemNode resolvePath1(RelevantPath path) {
11621162
)
11631163
}
11641164

1165-
pragma[nomagic]
1166-
private ItemNode resolvePathPrivate(
1167-
RelevantPath path, ModuleLikeNode itemParent, ModuleLikeNode pathParent
1168-
) {
1169-
not path.requiresExtractorWorkaround() and
1170-
result = resolvePath1(path) and
1171-
result.isPrivate() and
1172-
(
1173-
pathParent.getADescendant() = path
1174-
or
1175-
pathParent = any(ItemNode mid | path = mid.getADescendant()).getImmediateParentModule()
1176-
) and
1177-
(
1178-
itemParent = result.getVisibilityParent().getImmediateParentModule()
1179-
or
1180-
not result.hasVisibilityParent() and
1181-
itemParent = result.getImmediateParentModule()
1182-
)
1183-
}
1165+
/** Gets an item that `n` may resolve to, not taking visibility into account. */
1166+
signature ItemNode resolveCandidateSig(AstNode n);
11841167

1185-
pragma[nomagic]
1186-
private predicate isItemParent(ModuleLikeNode itemParent) {
1187-
exists(resolvePathPrivate(_, itemParent, _))
1188-
}
1168+
/** Provides the predicate `resolve` for resolving items while taking visibility into account. */
1169+
module ResolveWithVisibility<resolveCandidateSig/1 resolvePrivateCandidate> {
1170+
pragma[nomagic]
1171+
private ItemNode resolvePathPrivate(
1172+
AstNode n, ModuleLikeNode itemParent, ModuleLikeNode pathParent
1173+
) {
1174+
not n.(RelevantPath).requiresExtractorWorkaround() and
1175+
result = resolvePrivateCandidate(n) and
1176+
result.isPrivate() and
1177+
(
1178+
pathParent.getADescendant() = n
1179+
or
1180+
pathParent = any(ItemNode mid | n = mid.getADescendant()).getImmediateParentModule()
1181+
) and
1182+
(
1183+
itemParent = result.getVisibilityParent().getImmediateParentModule()
1184+
or
1185+
not result.hasVisibilityParent() and
1186+
itemParent = result.getImmediateParentModule()
1187+
)
1188+
}
11891189

1190-
/**
1191-
* Gets a module that has access to private items defined inside `itemParent`.
1192-
*
1193-
* According to [The Rust Reference][1] this is either `itemParent` itself or any
1194-
* descendant of `itemParent`.
1195-
*
1196-
* [1]: https://doc.rust-lang.org/reference/visibility-and-privacy.html#r-vis.access
1197-
*/
1198-
pragma[nomagic]
1199-
private ModuleLikeNode getAPrivateVisibleModule(ModuleLikeNode itemParent) {
1200-
isItemParent(itemParent) and
1201-
result.getImmediateParentModule*() = itemParent
1190+
pragma[nomagic]
1191+
private predicate isItemParent(ModuleLikeNode itemParent) {
1192+
exists(resolvePathPrivate(_, itemParent, _))
1193+
}
1194+
1195+
/**
1196+
* Gets a module that has access to private items defined inside `itemParent`.
1197+
*
1198+
* According to [The Rust Reference][1] this is either `itemParent` itself or any
1199+
* descendant of `itemParent`.
1200+
*
1201+
* [1]: https://doc.rust-lang.org/reference/visibility-and-privacy.html#r-vis.access
1202+
*/
1203+
pragma[nomagic]
1204+
private ModuleLikeNode getAPrivateVisibleModule(ModuleLikeNode itemParent) {
1205+
isItemParent(itemParent) and
1206+
result.getImmediateParentModule*() = itemParent
1207+
}
1208+
1209+
/** Gets an item that `n` may resolve to, taking visibility into account. */
1210+
ItemNode resolve(AstNode n) {
1211+
result = resolvePrivateCandidate(n) and
1212+
(
1213+
result.isPublic()
1214+
or
1215+
n.(RelevantPath).requiresExtractorWorkaround()
1216+
)
1217+
or
1218+
exists(ModuleLikeNode itemParent, ModuleLikeNode pathParent |
1219+
result = resolvePathPrivate(n, itemParent, pathParent) and
1220+
pathParent = getAPrivateVisibleModule(itemParent)
1221+
)
1222+
}
12021223
}
12031224

12041225
/** Gets the item that `path` resolves to, if any. */
12051226
cached
12061227
ItemNode resolvePath(RelevantPath path) {
1207-
result = resolvePath1(path) and
1208-
(
1209-
result.isPublic()
1210-
or
1211-
path.requiresExtractorWorkaround()
1212-
)
1213-
or
1214-
exists(ModuleLikeNode itemParent, ModuleLikeNode pathParent |
1215-
result = resolvePathPrivate(path, itemParent, pathParent) and
1216-
pathParent = getAPrivateVisibleModule(itemParent)
1217-
)
1228+
result = ResolveWithVisibility<resolvePathCand/1>::resolve(path)
12181229
}
12191230

12201231
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)