Skip to content

Commit 2854e25

Browse files
committed
Rust: Refine visibility check in path resolution
1 parent 2e0b568 commit 2854e25

3 files changed

Lines changed: 111 additions & 17 deletions

File tree

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]
@@ -243,10 +265,16 @@ private class SourceFileItemNode extends ModuleLikeNode, SourceFile {
243265
result.isType() // can be referenced with `super`
244266
}
245267

268+
override ItemNode getVisibilityParent() { none() }
269+
270+
override predicate hasVisibilityParent() { none() }
271+
246272
override Visibility getVisibility() { none() }
247273

248274
override predicate isPublic() { any() }
249275

276+
override predicate isPrivate() { none() }
277+
250278
override TypeParam getTypeParam(int i) { none() }
251279
}
252280

@@ -307,17 +335,45 @@ class CrateItemNode extends ItemNode instanceof Crate {
307335
result.isType() // can be referenced with `crate`
308336
}
309337

338+
override ItemNode getVisibilityParent() { none() }
339+
340+
override predicate hasVisibilityParent() { none() }
341+
310342
override Visibility getVisibility() { none() }
311343

312344
override predicate isPublic() { any() }
313345

346+
override predicate isPrivate() { none() }
347+
314348
override TypeParam getTypeParam(int i) { none() }
315349
}
316350

317351
/** An item that can occur in a trait or an `impl` block. */
318352
abstract private class AssocItemNode extends ItemNode, AssocItem {
319353
/** Holds if this associated item has an implementation. */
320354
abstract predicate hasImplementation();
355+
356+
override ItemNode getVisibilityParent() {
357+
exists(ImplItemNode i | this = i.getAnAssocItem() |
358+
// trait implementations inherit visibility from the trait
359+
result = i.resolveTraitTy()
360+
or
361+
// for inherent implementations that are not explicitly marked as
362+
// `pub`, the `impl` block itself must be visible
363+
not i.(Impl).hasTrait() and
364+
not exists(this.getVisibility()) and
365+
result = i
366+
)
367+
}
368+
369+
override predicate hasVisibilityParent() {
370+
exists(ImplItemNode i | this = i.getAnAssocItem() |
371+
i.(Impl).hasTrait()
372+
or
373+
not i.(Impl).hasTrait() and
374+
not exists(this.getVisibility())
375+
)
376+
}
321377
}
322378

323379
private class ConstItemNode extends AssocItemNode instanceof Const {
@@ -346,6 +402,10 @@ private class EnumItemNode extends ItemNode instanceof Enum {
346402

347403
override Namespace getNamespace() { result.isType() }
348404

405+
override ItemNode getVisibilityParent() { none() }
406+
407+
override predicate hasVisibilityParent() { none() }
408+
349409
override Visibility getVisibility() { result = Enum.super.getVisibility() }
350410

351411
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
@@ -362,7 +422,11 @@ private class VariantItemNode extends ItemNode instanceof Variant {
362422
result = super.getEnum().getGenericParamList().getTypeParam(i)
363423
}
364424

365-
override Visibility getVisibility() { result = super.getEnum().getVisibility() }
425+
override predicate hasVisibilityParent() { any() }
426+
427+
override ItemNode getVisibilityParent() { result = super.getEnum() }
428+
429+
override Visibility getVisibility() { none() }
366430
}
367431

368432
class FunctionItemNode extends AssocItemNode instanceof Function {
@@ -496,6 +560,10 @@ class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
496560

497561
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
498562

563+
override ItemNode getVisibilityParent() { none() }
564+
565+
override predicate hasVisibilityParent() { none() }
566+
499567
override Visibility getVisibility() { result = Impl.super.getVisibility() }
500568
}
501569

@@ -516,6 +584,10 @@ private class ModuleItemNode extends ModuleLikeNode instanceof Module {
516584

517585
override Namespace getNamespace() { result.isType() }
518586

587+
override ItemNode getVisibilityParent() { none() }
588+
589+
override predicate hasVisibilityParent() { none() }
590+
519591
override Visibility getVisibility() { result = Module.super.getVisibility() }
520592

521593
override TypeParam getTypeParam(int i) { none() }
@@ -531,6 +603,10 @@ private class StructItemNode extends ItemNode instanceof Struct {
531603
result.isValue() // the constructor
532604
}
533605

606+
override ItemNode getVisibilityParent() { none() }
607+
608+
override predicate hasVisibilityParent() { none() }
609+
534610
override Visibility getVisibility() { result = Struct.super.getVisibility() }
535611

536612
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
@@ -551,6 +627,10 @@ class TraitItemNode extends ImplOrTraitItemNode instanceof Trait {
551627

552628
override Namespace getNamespace() { result.isType() }
553629

630+
override ItemNode getVisibilityParent() { none() }
631+
632+
override predicate hasVisibilityParent() { none() }
633+
554634
override Visibility getVisibility() { result = Trait.super.getVisibility() }
555635

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

574654
override Namespace getNamespace() { result.isType() }
575655

656+
override ItemNode getVisibilityParent() { none() }
657+
658+
override predicate hasVisibilityParent() { none() }
659+
576660
override Visibility getVisibility() { result = Union.super.getVisibility() }
577661

578662
override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) }
@@ -583,6 +667,10 @@ private class UseItemNode extends ItemNode instanceof Use {
583667

584668
override Namespace getNamespace() { none() }
585669

670+
override ItemNode getVisibilityParent() { none() }
671+
672+
override predicate hasVisibilityParent() { none() }
673+
586674
override Visibility getVisibility() { result = Use.super.getVisibility() }
587675

588676
override TypeParam getTypeParam(int i) { none() }
@@ -593,6 +681,10 @@ private class BlockExprItemNode extends ItemNode instanceof BlockExpr {
593681

594682
override Namespace getNamespace() { none() }
595683

684+
override ItemNode getVisibilityParent() { none() }
685+
686+
override predicate hasVisibilityParent() { none() }
687+
596688
override Visibility getVisibility() { none() }
597689

598690
override TypeParam getTypeParam(int i) { none() }
@@ -656,6 +748,10 @@ class TypeParamItemNode extends ItemNode instanceof TypeParam {
656748

657749
override Namespace getNamespace() { result.isType() }
658750

751+
override ItemNode getVisibilityParent() { none() }
752+
753+
override predicate hasVisibilityParent() { none() }
754+
659755
override Visibility getVisibility() { none() }
660756

661757
override TypeParam getTypeParam(int i) { none() }
@@ -1055,12 +1151,17 @@ private ItemNode resolvePathPrivate(
10551151
) {
10561152
not path.requiresExtractorWorkaround() and
10571153
result = resolvePath1(path) and
1058-
itemParent = result.getImmediateParentModule() and
1059-
not result.isPublic() and
1154+
result.isPrivate() and
10601155
(
10611156
pathParent.getADescendant() = path
10621157
or
10631158
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()
10641165
)
10651166
}
10661167

@@ -1205,19 +1306,11 @@ private module Debug {
12051306
private Locatable getRelevantLocatable() {
12061307
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
12071308
result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
1208-
filepath.matches("%/test_logging.rs") and
1209-
startline = 163
1309+
filepath.matches("%/illegal/main.rs") and
1310+
startline = 51
12101311
)
12111312
}
12121313

1213-
predicate debugUnqualifiedPathLookup(
1214-
RelevantPath p, string name, Namespace ns, ItemNode encl, string path
1215-
) {
1216-
p = getRelevantLocatable() and
1217-
unqualifiedPathLookup(p, name, ns, encl) and
1218-
path = p.toStringDebug()
1219-
}
1220-
12211314
ItemNode debugResolvePath(RelevantPath path) {
12221315
path = getRelevantLocatable() and
12231316
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)