Skip to content

Commit f3c5646

Browse files
committed
Rust: Also check visibility in method call resolution
1 parent 2854e25 commit f3c5646

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
@@ -1136,7 +1136,7 @@ private predicate pathUsesNamespace(Path p, Namespace n) {
11361136
}
11371137

11381138
pragma[nomagic]
1139-
private ItemNode resolvePath1(RelevantPath path) {
1139+
private ItemNode resolvePathCand(AstNode path) {
11401140
exists(Namespace ns | result = resolvePath0(path, ns) |
11411141
pathUsesNamespace(path, ns)
11421142
or
@@ -1145,59 +1145,70 @@ private ItemNode resolvePath1(RelevantPath path) {
11451145
)
11461146
}
11471147

1148-
pragma[nomagic]
1149-
private ItemNode resolvePathPrivate(
1150-
RelevantPath path, ModuleLikeNode itemParent, ModuleLikeNode pathParent
1151-
) {
1152-
not path.requiresExtractorWorkaround() and
1153-
result = resolvePath1(path) and
1154-
result.isPrivate() and
1155-
(
1156-
pathParent.getADescendant() = path
1157-
or
1158-
pathParent = any(ItemNode mid | path = mid.getADescendant()).getImmediateParentModule()
1159-
) and
1160-
(
1161-
itemParent = result.getVisibilityParent().getImmediateParentModule()
1162-
or
1163-
not result.hasVisibilityParent() and
1164-
itemParent = result.getImmediateParentModule()
1165-
)
1166-
}
1148+
/** Gets an item that `n` may resolve to, not taking visibility into account. */
1149+
signature ItemNode resolveCandidateSig(AstNode n);
11671150

1168-
pragma[nomagic]
1169-
private predicate isItemParent(ModuleLikeNode itemParent) {
1170-
exists(resolvePathPrivate(_, itemParent, _))
1171-
}
1151+
/** Provides the predicate `resolve` for resolving items while taking visibility into account. */
1152+
module ResolveWithVisibility<resolveCandidateSig/1 resolvePrivateCandidate> {
1153+
pragma[nomagic]
1154+
private ItemNode resolvePathPrivate(
1155+
AstNode n, ModuleLikeNode itemParent, ModuleLikeNode pathParent
1156+
) {
1157+
not n.(RelevantPath).requiresExtractorWorkaround() and
1158+
result = resolvePrivateCandidate(n) and
1159+
result.isPrivate() and
1160+
(
1161+
pathParent.getADescendant() = n
1162+
or
1163+
pathParent = any(ItemNode mid | n = mid.getADescendant()).getImmediateParentModule()
1164+
) and
1165+
(
1166+
itemParent = result.getVisibilityParent().getImmediateParentModule()
1167+
or
1168+
not result.hasVisibilityParent() and
1169+
itemParent = result.getImmediateParentModule()
1170+
)
1171+
}
11721172

1173-
/**
1174-
* Gets a module that has access to private items defined inside `itemParent`.
1175-
*
1176-
* According to [The Rust Reference][1] this is either `itemParent` itself or any
1177-
* descendant of `itemParent`.
1178-
*
1179-
* [1]: https://doc.rust-lang.org/reference/visibility-and-privacy.html#r-vis.access
1180-
*/
1181-
pragma[nomagic]
1182-
private ModuleLikeNode getAPrivateVisibleModule(ModuleLikeNode itemParent) {
1183-
isItemParent(itemParent) and
1184-
result.getImmediateParentModule*() = itemParent
1173+
pragma[nomagic]
1174+
private predicate isItemParent(ModuleLikeNode itemParent) {
1175+
exists(resolvePathPrivate(_, itemParent, _))
1176+
}
1177+
1178+
/**
1179+
* Gets a module that has access to private items defined inside `itemParent`.
1180+
*
1181+
* According to [The Rust Reference][1] this is either `itemParent` itself or any
1182+
* descendant of `itemParent`.
1183+
*
1184+
* [1]: https://doc.rust-lang.org/reference/visibility-and-privacy.html#r-vis.access
1185+
*/
1186+
pragma[nomagic]
1187+
private ModuleLikeNode getAPrivateVisibleModule(ModuleLikeNode itemParent) {
1188+
isItemParent(itemParent) and
1189+
result.getImmediateParentModule*() = itemParent
1190+
}
1191+
1192+
/** Gets an item that `n` may resolve to, taking visibility into account. */
1193+
ItemNode resolve(AstNode n) {
1194+
result = resolvePrivateCandidate(n) and
1195+
(
1196+
result.isPublic()
1197+
or
1198+
n.(RelevantPath).requiresExtractorWorkaround()
1199+
)
1200+
or
1201+
exists(ModuleLikeNode itemParent, ModuleLikeNode pathParent |
1202+
result = resolvePathPrivate(n, itemParent, pathParent) and
1203+
pathParent = getAPrivateVisibleModule(itemParent)
1204+
)
1205+
}
11851206
}
11861207

11871208
/** Gets the item that `path` resolves to, if any. */
11881209
cached
11891210
ItemNode resolvePath(RelevantPath path) {
1190-
result = resolvePath1(path) and
1191-
(
1192-
result.isPublic()
1193-
or
1194-
path.requiresExtractorWorkaround()
1195-
)
1196-
or
1197-
exists(ModuleLikeNode itemParent, ModuleLikeNode pathParent |
1198-
result = resolvePathPrivate(path, itemParent, pathParent) and
1199-
pathParent = getAPrivateVisibleModule(itemParent)
1200-
)
1211+
result = ResolveWithVisibility<resolvePathCand/1>::resolve(path)
12011212
}
12021213

12031214
pragma[nomagic]

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

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

928+
private ItemNode resolveMethodCallExprCand(AstNode mce) {
929+
exists(string name | result = getMethodCallExprLookupType(mce, name).getMethod(name))
930+
}
931+
928932
/**
929933
* Gets a method that the method call `mce` resolves to, if any.
930934
*/
931935
cached
932936
Function resolveMethodCallExpr(MethodCallExpr mce) {
933-
exists(string name | result = getMethodCallExprLookupType(mce, name).getMethod(name))
937+
result = ResolveWithVisibility<resolveMethodCallExprCand/1>::resolve(mce)
934938
}
935939

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