Skip to content

Commit e7aa3cb

Browse files
committed
Rust: Refine visibility check in path resolution
1 parent a16c4ab commit e7aa3cb

File tree

3 files changed

+111
-17
lines changed

3 files changed

+111
-17
lines changed

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

Lines changed: 109 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,32 @@ abstract class ItemNode extends Locatable {
8787
/** Gets the `i`th type parameter of this item, if any. */
8888
abstract TypeParam getTypeParam(int i);
8989

90+
/** Gets the parent item from which this node inherits visibility, if any. */
91+
abstract ItemNode getVisibilityParent();
92+
93+
/** Holds if this item has a visibility parent. */
94+
// Cannot be defined as `exists(this.getVisibilityParent())` because of non-monotonicity
95+
abstract predicate hasVisibilityParent();
96+
9097
/** Holds if this item is declared as `pub`. */
91-
bindingset[this]
92-
pragma[inline_late]
93-
predicate isPublic() { exists(this.getVisibility()) }
98+
pragma[nomagic]
99+
predicate isPublic() {
100+
exists(this.getVisibility())
101+
or
102+
this.getVisibilityParent().isPublic()
103+
}
104+
105+
/** Holds if this item is not declared as `pub`. */
106+
pragma[nomagic]
107+
predicate isPrivate() {
108+
// Cannot be defined as `not this.isPublic()` because of non-monotonicity
109+
not exists(this.getVisibility()) and
110+
(
111+
not this.hasVisibilityParent()
112+
or
113+
this.getVisibilityParent().isPrivate()
114+
)
115+
}
94116

95117
/** Gets an element that has this item as immediately enclosing item. */
96118
pragma[nomagic]
@@ -264,10 +286,16 @@ private class SourceFileItemNode extends ModuleLikeNode, SourceFile {
264286
result.isType() // can be referenced with `super`
265287
}
266288

289+
override ItemNode getVisibilityParent() { none() }
290+
291+
override predicate hasVisibilityParent() { none() }
292+
267293
override Visibility getVisibility() { none() }
268294

269295
override predicate isPublic() { any() }
270296

297+
override predicate isPrivate() { none() }
298+
271299
override TypeParam getTypeParam(int i) { none() }
272300
}
273301

@@ -328,17 +356,45 @@ class CrateItemNode extends ItemNode instanceof Crate {
328356
result.isType() // can be referenced with `crate`
329357
}
330358

359+
override ItemNode getVisibilityParent() { none() }
360+
361+
override predicate hasVisibilityParent() { none() }
362+
331363
override Visibility getVisibility() { none() }
332364

333365
override predicate isPublic() { any() }
334366

367+
override predicate isPrivate() { none() }
368+
335369
override TypeParam getTypeParam(int i) { none() }
336370
}
337371

338372
/** An item that can occur in a trait or an `impl` block. */
339373
abstract private class AssocItemNode extends ItemNode, AssocItem {
340374
/** Holds if this associated item has an implementation. */
341375
abstract predicate hasImplementation();
376+
377+
override ItemNode getVisibilityParent() {
378+
exists(ImplItemNode i | this = i.getAnAssocItem() |
379+
// trait implementations inherit visibility from the trait
380+
result = i.resolveTraitTy()
381+
or
382+
// for inherent implementations that are not explicitly marked as
383+
// `pub`, the `impl` block itself must be visible
384+
not i.(Impl).hasTrait() and
385+
not exists(this.getVisibility()) and
386+
result = i
387+
)
388+
}
389+
390+
override predicate hasVisibilityParent() {
391+
exists(ImplItemNode i | this = i.getAnAssocItem() |
392+
i.(Impl).hasTrait()
393+
or
394+
not i.(Impl).hasTrait() and
395+
not exists(this.getVisibility())
396+
)
397+
}
342398
}
343399

344400
private class ConstItemNode extends AssocItemNode instanceof Const {
@@ -365,6 +421,10 @@ private class EnumItemNode extends ItemNode instanceof Enum {
365421

366422
override Namespace getNamespace() { result.isType() }
367423

424+
override ItemNode getVisibilityParent() { none() }
425+
426+
override predicate hasVisibilityParent() { none() }
427+
368428
override Visibility getVisibility() { result = Enum.super.getVisibility() }
369429

370430
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
@@ -381,7 +441,11 @@ private class VariantItemNode extends ItemNode instanceof Variant {
381441
result = super.getEnum().getGenericParamList().getTypeParam(i)
382442
}
383443

384-
override Visibility getVisibility() { result = super.getEnum().getVisibility() }
444+
override predicate hasVisibilityParent() { any() }
445+
446+
override ItemNode getVisibilityParent() { result = super.getEnum() }
447+
448+
override Visibility getVisibility() { none() }
385449
}
386450

387451
class FunctionItemNode extends AssocItemNode instanceof Function {
@@ -513,6 +577,10 @@ class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
513577

514578
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
515579

580+
override ItemNode getVisibilityParent() { none() }
581+
582+
override predicate hasVisibilityParent() { none() }
583+
516584
override Visibility getVisibility() { result = Impl.super.getVisibility() }
517585
}
518586

@@ -533,6 +601,10 @@ private class ModuleItemNode extends ModuleLikeNode instanceof Module {
533601

534602
override Namespace getNamespace() { result.isType() }
535603

604+
override ItemNode getVisibilityParent() { none() }
605+
606+
override predicate hasVisibilityParent() { none() }
607+
536608
override Visibility getVisibility() { result = Module.super.getVisibility() }
537609

538610
override TypeParam getTypeParam(int i) { none() }
@@ -548,6 +620,10 @@ private class StructItemNode extends ItemNode instanceof Struct {
548620
result.isValue() // the constructor
549621
}
550622

623+
override ItemNode getVisibilityParent() { none() }
624+
625+
override predicate hasVisibilityParent() { none() }
626+
551627
override Visibility getVisibility() { result = Struct.super.getVisibility() }
552628

553629
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
@@ -568,6 +644,10 @@ class TraitItemNode extends ImplOrTraitItemNode instanceof Trait {
568644

569645
override Namespace getNamespace() { result.isType() }
570646

647+
override ItemNode getVisibilityParent() { none() }
648+
649+
override predicate hasVisibilityParent() { none() }
650+
571651
override Visibility getVisibility() { result = Trait.super.getVisibility() }
572652

573653
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
@@ -590,6 +670,10 @@ private class UnionItemNode extends ItemNode instanceof Union {
590670

591671
override Namespace getNamespace() { result.isType() }
592672

673+
override ItemNode getVisibilityParent() { none() }
674+
675+
override predicate hasVisibilityParent() { none() }
676+
593677
override Visibility getVisibility() { result = Union.super.getVisibility() }
594678

595679
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
@@ -600,6 +684,10 @@ private class UseItemNode extends ItemNode instanceof Use {
600684

601685
override Namespace getNamespace() { none() }
602686

687+
override ItemNode getVisibilityParent() { none() }
688+
689+
override predicate hasVisibilityParent() { none() }
690+
603691
override Visibility getVisibility() { result = Use.super.getVisibility() }
604692

605693
override TypeParam getTypeParam(int i) { none() }
@@ -610,6 +698,10 @@ private class BlockExprItemNode extends ItemNode instanceof BlockExpr {
610698

611699
override Namespace getNamespace() { none() }
612700

701+
override ItemNode getVisibilityParent() { none() }
702+
703+
override predicate hasVisibilityParent() { none() }
704+
613705
override Visibility getVisibility() { none() }
614706

615707
override TypeParam getTypeParam(int i) { none() }
@@ -673,6 +765,10 @@ class TypeParamItemNode extends ItemNode instanceof TypeParam {
673765

674766
override Namespace getNamespace() { result.isType() }
675767

768+
override ItemNode getVisibilityParent() { none() }
769+
770+
override predicate hasVisibilityParent() { none() }
771+
676772
override Visibility getVisibility() { none() }
677773

678774
override TypeParam getTypeParam(int i) { none() }
@@ -1072,12 +1168,17 @@ private ItemNode resolvePathPrivate(
10721168
) {
10731169
not path.requiresExtractorWorkaround() and
10741170
result = resolvePath1(path) and
1075-
itemParent = result.getImmediateParentModule() and
1076-
not result.isPublic() and
1171+
result.isPrivate() and
10771172
(
10781173
pathParent.getADescendant() = path
10791174
or
10801175
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()
10811182
)
10821183
}
10831184

@@ -1222,19 +1323,11 @@ private module Debug {
12221323
private Locatable getRelevantLocatable() {
12231324
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
12241325
result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
1225-
filepath.matches("%/test_logging.rs") and
1226-
startline = 163
1326+
filepath.matches("%/illegal/main.rs") and
1327+
startline = 51
12271328
)
12281329
}
12291330

1230-
predicate debugUnqualifiedPathLookup(
1231-
RelevantPath p, string name, Namespace ns, ItemNode encl, string path
1232-
) {
1233-
p = getRelevantLocatable() and
1234-
unqualifiedPathLookup(p, name, ns, encl) and
1235-
path = p.toStringDebug()
1236-
}
1237-
12381331
ItemNode debugResolvePath(RelevantPath path) {
12391332
path = getRelevantLocatable() and
12401333
result = resolvePath(path)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ mod m1 {
5858
);
5959
super::S(). // $ item=I1
6060
f1(); // $ item=I6
61-
super::S::f1( // $ MISSING: item=I6
61+
super::S::f1( // $ item=I6
6262
super::S() // $ item=I1
6363
);
6464
super::S(). // $ item=I1

rust/ql/test/library-tests/path-resolution/path-resolution.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ resolvePath
7777
| illegal/main.rs:59:13:59:20 | ...::S | illegal/main.rs:2:5:2:15 | struct S |
7878
| illegal/main.rs:61:13:61:17 | super | illegal/main.rs:1:1:71:1 | mod m1 |
7979
| illegal/main.rs:61:13:61:20 | ...::S | illegal/main.rs:2:5:2:15 | struct S |
80+
| illegal/main.rs:61:13:61:24 | ...::f1 | illegal/main.rs:27:24:30:13 | fn f1 |
8081
| illegal/main.rs:62:17:62:21 | super | illegal/main.rs:1:1:71:1 | mod m1 |
8182
| illegal/main.rs:62:17:62:24 | ...::S | illegal/main.rs:2:5:2:15 | struct S |
8283
| illegal/main.rs:64:13:64:17 | super | illegal/main.rs:1:1:71:1 | mod m1 |

0 commit comments

Comments
 (0)