From a16c4abef8b40abcc97ac7fbffa559b73cc254a5 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 29 Apr 2025 14:49:00 +0200 Subject: [PATCH 1/4] Rust: Add more path resolution tests --- .../path-resolution/illegal/main.rs | 71 +++++++++++++++++++ .../path-resolution/illegal/options.yml | 1 + .../path-resolution/path-resolution.expected | 41 +++++++++++ 3 files changed, 113 insertions(+) create mode 100644 rust/ql/test/library-tests/path-resolution/illegal/main.rs create mode 100644 rust/ql/test/library-tests/path-resolution/illegal/options.yml diff --git a/rust/ql/test/library-tests/path-resolution/illegal/main.rs b/rust/ql/test/library-tests/path-resolution/illegal/main.rs new file mode 100644 index 000000000000..eb29f428705b --- /dev/null +++ b/rust/ql/test/library-tests/path-resolution/illegal/main.rs @@ -0,0 +1,71 @@ +mod m1 { + struct S(); // I1 + + trait T1 { + fn f1(&self); + } // I2 + + mod nested1 { + + trait T2 { + fn f2(&self); + } // I3 + + #[rustfmt::skip] + impl super::S { // $ item=I1 + fn f(self) { + println!("m1::S::f"); + } // I4 + + pub fn g(self) { + println!("m1::S::f"); + } // I5 + } + + #[rustfmt::skip] + impl super::T1 // $ item=I2 + for super::S { // $ item=I1 + fn f1(&self) { + println!("m1::nested1::T2::f"); + } // I6 + } + + #[rustfmt::skip] + impl T2 // $ item=I3 + for super::S { // $ item=I1 + fn f2(&self) { + println!("m1::nested1::T2::f"); + } // I7 + } + } + + mod nested2 { + use super::nested1::T2; // illegal: private + use super::T1; // $ item=I2 + + #[rustfmt::skip] + pub fn f() { + println!("m1::nested2::f"); + super::S(). // $ item=I1 + f(); // $ SPURIOUS: item=I4 (private) + super::S::f( // illegal: private + super::S() // $ item=I1 + ); + super::S(). // $ item=I1 + g(); // $ item=I5 + super::S::g( // $ item=I5 + super::S() // $ item=I1 + ); + super::S(). // $ item=I1 + f1(); // $ item=I6 + super::S::f1( // $ MISSING: item=I6 + super::S() // $ item=I1 + ); + super::S(). // $ item=I1 + f2(); // $ SPURIOUS: item=I7 (private) + super::S::f2( + super::S() // $ item=I1 + ); // illegal: private + } + } +} diff --git a/rust/ql/test/library-tests/path-resolution/illegal/options.yml b/rust/ql/test/library-tests/path-resolution/illegal/options.yml new file mode 100644 index 000000000000..cf148dd35f86 --- /dev/null +++ b/rust/ql/test/library-tests/path-resolution/illegal/options.yml @@ -0,0 +1 @@ +qltest_cargo_check: false diff --git a/rust/ql/test/library-tests/path-resolution/path-resolution.expected b/rust/ql/test/library-tests/path-resolution/path-resolution.expected index 90af94e91d00..44d599b39192 100644 --- a/rust/ql/test/library-tests/path-resolution/path-resolution.expected +++ b/rust/ql/test/library-tests/path-resolution/path-resolution.expected @@ -1,5 +1,8 @@ testFailures mod +| illegal/main.rs:1:1:71:1 | mod m1 | +| illegal/main.rs:8:5:40:5 | mod nested1 | +| illegal/main.rs:42:5:70:5 | mod nested2 | | lib.rs:1:1:1:7 | mod my | | main.rs:1:1:1:7 | mod my | | main.rs:7:1:7:8 | mod my2 | @@ -44,6 +47,44 @@ mod | my/nested.rs:1:1:17:1 | mod nested1 | | my/nested.rs:2:5:11:5 | mod nested2 | resolvePath +| illegal/main.rs:15:14:15:18 | super | illegal/main.rs:1:1:71:1 | mod m1 | +| illegal/main.rs:15:14:15:21 | ...::S | illegal/main.rs:2:5:2:15 | struct S | +| illegal/main.rs:26:14:26:18 | super | illegal/main.rs:1:1:71:1 | mod m1 | +| illegal/main.rs:26:14:26:22 | ...::T1 | illegal/main.rs:4:5:6:5 | trait T1 | +| illegal/main.rs:27:13:27:17 | super | illegal/main.rs:1:1:71:1 | mod m1 | +| illegal/main.rs:27:13:27:20 | ...::S | illegal/main.rs:2:5:2:15 | struct S | +| illegal/main.rs:34:14:34:15 | T2 | illegal/main.rs:10:9:12:9 | trait T2 | +| illegal/main.rs:35:13:35:17 | super | illegal/main.rs:1:1:71:1 | mod m1 | +| illegal/main.rs:35:13:35:20 | ...::S | illegal/main.rs:2:5:2:15 | struct S | +| illegal/main.rs:43:13:43:17 | super | illegal/main.rs:1:1:71:1 | mod m1 | +| illegal/main.rs:43:13:43:26 | ...::nested1 | illegal/main.rs:8:5:40:5 | mod nested1 | +| illegal/main.rs:44:13:44:17 | super | illegal/main.rs:1:1:71:1 | mod m1 | +| illegal/main.rs:44:13:44:21 | ...::T1 | illegal/main.rs:4:5:6:5 | trait T1 | +| illegal/main.rs:49:13:49:17 | super | illegal/main.rs:1:1:71:1 | mod m1 | +| illegal/main.rs:49:13:49:20 | ...::S | illegal/main.rs:2:5:2:15 | struct S | +| illegal/main.rs:51:13:51:17 | super | illegal/main.rs:1:1:71:1 | mod m1 | +| illegal/main.rs:51:13:51:20 | ...::S | illegal/main.rs:2:5:2:15 | struct S | +| illegal/main.rs:52:17:52:21 | super | illegal/main.rs:1:1:71:1 | mod m1 | +| illegal/main.rs:52:17:52:24 | ...::S | illegal/main.rs:2:5:2:15 | struct S | +| illegal/main.rs:54:13:54:17 | super | illegal/main.rs:1:1:71:1 | mod m1 | +| illegal/main.rs:54:13:54:20 | ...::S | illegal/main.rs:2:5:2:15 | struct S | +| illegal/main.rs:56:13:56:17 | super | illegal/main.rs:1:1:71:1 | mod m1 | +| illegal/main.rs:56:13:56:20 | ...::S | illegal/main.rs:2:5:2:15 | struct S | +| illegal/main.rs:56:13:56:23 | ...::g | illegal/main.rs:20:13:22:13 | fn g | +| illegal/main.rs:57:17:57:21 | super | illegal/main.rs:1:1:71:1 | mod m1 | +| illegal/main.rs:57:17:57:24 | ...::S | illegal/main.rs:2:5:2:15 | struct S | +| illegal/main.rs:59:13:59:17 | super | illegal/main.rs:1:1:71:1 | mod m1 | +| illegal/main.rs:59:13:59:20 | ...::S | illegal/main.rs:2:5:2:15 | struct S | +| illegal/main.rs:61:13:61:17 | super | illegal/main.rs:1:1:71:1 | mod m1 | +| illegal/main.rs:61:13:61:20 | ...::S | illegal/main.rs:2:5:2:15 | struct S | +| illegal/main.rs:62:17:62:21 | super | illegal/main.rs:1:1:71:1 | mod m1 | +| illegal/main.rs:62:17:62:24 | ...::S | illegal/main.rs:2:5:2:15 | struct S | +| illegal/main.rs:64:13:64:17 | super | illegal/main.rs:1:1:71:1 | mod m1 | +| illegal/main.rs:64:13:64:20 | ...::S | illegal/main.rs:2:5:2:15 | struct S | +| illegal/main.rs:66:13:66:17 | super | illegal/main.rs:1:1:71:1 | mod m1 | +| illegal/main.rs:66:13:66:20 | ...::S | illegal/main.rs:2:5:2:15 | struct S | +| illegal/main.rs:67:17:67:21 | super | illegal/main.rs:1:1:71:1 | mod m1 | +| illegal/main.rs:67:17:67:24 | ...::S | illegal/main.rs:2:5:2:15 | struct S | | main.rs:3:5:3:6 | my | main.rs:1:1:1:7 | mod my | | main.rs:5:5:5:6 | my | main.rs:1:1:1:7 | mod my | | main.rs:5:5:5:14 | ...::nested | my.rs:1:1:1:15 | mod nested | From e7aa3cba39a81f029b5b9fa066b007756b00d95e Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 29 Apr 2025 14:10:34 +0200 Subject: [PATCH 2/4] Rust: Refine visibility check in path resolution --- .../codeql/rust/internal/PathResolution.qll | 125 +++++++++++++++--- .../path-resolution/illegal/main.rs | 2 +- .../path-resolution/path-resolution.expected | 1 + 3 files changed, 111 insertions(+), 17 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/PathResolution.qll b/rust/ql/lib/codeql/rust/internal/PathResolution.qll index 5bc45afecf17..cfb821adbfbd 100644 --- a/rust/ql/lib/codeql/rust/internal/PathResolution.qll +++ b/rust/ql/lib/codeql/rust/internal/PathResolution.qll @@ -87,10 +87,32 @@ abstract class ItemNode extends Locatable { /** Gets the `i`th type parameter of this item, if any. */ abstract TypeParam getTypeParam(int i); + /** Gets the parent item from which this node inherits visibility, if any. */ + abstract ItemNode getVisibilityParent(); + + /** Holds if this item has a visibility parent. */ + // Cannot be defined as `exists(this.getVisibilityParent())` because of non-monotonicity + abstract predicate hasVisibilityParent(); + /** Holds if this item is declared as `pub`. */ - bindingset[this] - pragma[inline_late] - predicate isPublic() { exists(this.getVisibility()) } + pragma[nomagic] + predicate isPublic() { + exists(this.getVisibility()) + or + this.getVisibilityParent().isPublic() + } + + /** Holds if this item is not declared as `pub`. */ + pragma[nomagic] + predicate isPrivate() { + // Cannot be defined as `not this.isPublic()` because of non-monotonicity + not exists(this.getVisibility()) and + ( + not this.hasVisibilityParent() + or + this.getVisibilityParent().isPrivate() + ) + } /** Gets an element that has this item as immediately enclosing item. */ pragma[nomagic] @@ -264,10 +286,16 @@ private class SourceFileItemNode extends ModuleLikeNode, SourceFile { result.isType() // can be referenced with `super` } + override ItemNode getVisibilityParent() { none() } + + override predicate hasVisibilityParent() { none() } + override Visibility getVisibility() { none() } override predicate isPublic() { any() } + override predicate isPrivate() { none() } + override TypeParam getTypeParam(int i) { none() } } @@ -328,10 +356,16 @@ class CrateItemNode extends ItemNode instanceof Crate { result.isType() // can be referenced with `crate` } + override ItemNode getVisibilityParent() { none() } + + override predicate hasVisibilityParent() { none() } + override Visibility getVisibility() { none() } override predicate isPublic() { any() } + override predicate isPrivate() { none() } + override TypeParam getTypeParam(int i) { none() } } @@ -339,6 +373,28 @@ class CrateItemNode extends ItemNode instanceof Crate { abstract private class AssocItemNode extends ItemNode, AssocItem { /** Holds if this associated item has an implementation. */ abstract predicate hasImplementation(); + + override ItemNode getVisibilityParent() { + exists(ImplItemNode i | this = i.getAnAssocItem() | + // trait implementations inherit visibility from the trait + result = i.resolveTraitTy() + or + // for inherent implementations that are not explicitly marked as + // `pub`, the `impl` block itself must be visible + not i.(Impl).hasTrait() and + not exists(this.getVisibility()) and + result = i + ) + } + + override predicate hasVisibilityParent() { + exists(ImplItemNode i | this = i.getAnAssocItem() | + i.(Impl).hasTrait() + or + not i.(Impl).hasTrait() and + not exists(this.getVisibility()) + ) + } } private class ConstItemNode extends AssocItemNode instanceof Const { @@ -365,6 +421,10 @@ private class EnumItemNode extends ItemNode instanceof Enum { override Namespace getNamespace() { result.isType() } + override ItemNode getVisibilityParent() { none() } + + override predicate hasVisibilityParent() { none() } + override Visibility getVisibility() { result = Enum.super.getVisibility() } override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) } @@ -381,7 +441,11 @@ private class VariantItemNode extends ItemNode instanceof Variant { result = super.getEnum().getGenericParamList().getTypeParam(i) } - override Visibility getVisibility() { result = super.getEnum().getVisibility() } + override predicate hasVisibilityParent() { any() } + + override ItemNode getVisibilityParent() { result = super.getEnum() } + + override Visibility getVisibility() { none() } } class FunctionItemNode extends AssocItemNode instanceof Function { @@ -513,6 +577,10 @@ class ImplItemNode extends ImplOrTraitItemNode instanceof Impl { override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) } + override ItemNode getVisibilityParent() { none() } + + override predicate hasVisibilityParent() { none() } + override Visibility getVisibility() { result = Impl.super.getVisibility() } } @@ -533,6 +601,10 @@ private class ModuleItemNode extends ModuleLikeNode instanceof Module { override Namespace getNamespace() { result.isType() } + override ItemNode getVisibilityParent() { none() } + + override predicate hasVisibilityParent() { none() } + override Visibility getVisibility() { result = Module.super.getVisibility() } override TypeParam getTypeParam(int i) { none() } @@ -548,6 +620,10 @@ private class StructItemNode extends ItemNode instanceof Struct { result.isValue() // the constructor } + override ItemNode getVisibilityParent() { none() } + + override predicate hasVisibilityParent() { none() } + override Visibility getVisibility() { result = Struct.super.getVisibility() } override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) } @@ -568,6 +644,10 @@ class TraitItemNode extends ImplOrTraitItemNode instanceof Trait { override Namespace getNamespace() { result.isType() } + override ItemNode getVisibilityParent() { none() } + + override predicate hasVisibilityParent() { none() } + override Visibility getVisibility() { result = Trait.super.getVisibility() } override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) } @@ -590,6 +670,10 @@ private class UnionItemNode extends ItemNode instanceof Union { override Namespace getNamespace() { result.isType() } + override ItemNode getVisibilityParent() { none() } + + override predicate hasVisibilityParent() { none() } + override Visibility getVisibility() { result = Union.super.getVisibility() } override TypeParam getTypeParam(int i) { result = super.getGenericParamList().getTypeParam(i) } @@ -600,6 +684,10 @@ private class UseItemNode extends ItemNode instanceof Use { override Namespace getNamespace() { none() } + override ItemNode getVisibilityParent() { none() } + + override predicate hasVisibilityParent() { none() } + override Visibility getVisibility() { result = Use.super.getVisibility() } override TypeParam getTypeParam(int i) { none() } @@ -610,6 +698,10 @@ private class BlockExprItemNode extends ItemNode instanceof BlockExpr { override Namespace getNamespace() { none() } + override ItemNode getVisibilityParent() { none() } + + override predicate hasVisibilityParent() { none() } + override Visibility getVisibility() { none() } override TypeParam getTypeParam(int i) { none() } @@ -673,6 +765,10 @@ class TypeParamItemNode extends ItemNode instanceof TypeParam { override Namespace getNamespace() { result.isType() } + override ItemNode getVisibilityParent() { none() } + + override predicate hasVisibilityParent() { none() } + override Visibility getVisibility() { none() } override TypeParam getTypeParam(int i) { none() } @@ -1072,12 +1168,17 @@ private ItemNode resolvePathPrivate( ) { not path.requiresExtractorWorkaround() and result = resolvePath1(path) and - itemParent = result.getImmediateParentModule() and - not result.isPublic() and + result.isPrivate() and ( pathParent.getADescendant() = path or pathParent = any(ItemNode mid | path = mid.getADescendant()).getImmediateParentModule() + ) and + ( + itemParent = result.getVisibilityParent().getImmediateParentModule() + or + not result.hasVisibilityParent() and + itemParent = result.getImmediateParentModule() ) } @@ -1222,19 +1323,11 @@ private module Debug { private Locatable getRelevantLocatable() { exists(string filepath, int startline, int startcolumn, int endline, int endcolumn | result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and - filepath.matches("%/test_logging.rs") and - startline = 163 + filepath.matches("%/illegal/main.rs") and + startline = 51 ) } - predicate debugUnqualifiedPathLookup( - RelevantPath p, string name, Namespace ns, ItemNode encl, string path - ) { - p = getRelevantLocatable() and - unqualifiedPathLookup(p, name, ns, encl) and - path = p.toStringDebug() - } - ItemNode debugResolvePath(RelevantPath path) { path = getRelevantLocatable() and result = resolvePath(path) diff --git a/rust/ql/test/library-tests/path-resolution/illegal/main.rs b/rust/ql/test/library-tests/path-resolution/illegal/main.rs index eb29f428705b..c02f4cc9bf82 100644 --- a/rust/ql/test/library-tests/path-resolution/illegal/main.rs +++ b/rust/ql/test/library-tests/path-resolution/illegal/main.rs @@ -58,7 +58,7 @@ mod m1 { ); super::S(). // $ item=I1 f1(); // $ item=I6 - super::S::f1( // $ MISSING: item=I6 + super::S::f1( // $ item=I6 super::S() // $ item=I1 ); super::S(). // $ item=I1 diff --git a/rust/ql/test/library-tests/path-resolution/path-resolution.expected b/rust/ql/test/library-tests/path-resolution/path-resolution.expected index 44d599b39192..c7e262e1d4bf 100644 --- a/rust/ql/test/library-tests/path-resolution/path-resolution.expected +++ b/rust/ql/test/library-tests/path-resolution/path-resolution.expected @@ -77,6 +77,7 @@ resolvePath | illegal/main.rs:59:13:59:20 | ...::S | illegal/main.rs:2:5:2:15 | struct S | | illegal/main.rs:61:13:61:17 | super | illegal/main.rs:1:1:71:1 | mod m1 | | illegal/main.rs:61:13:61:20 | ...::S | illegal/main.rs:2:5:2:15 | struct S | +| illegal/main.rs:61:13:61:24 | ...::f1 | illegal/main.rs:27:24:30:13 | fn f1 | | illegal/main.rs:62:17:62:21 | super | illegal/main.rs:1:1:71:1 | mod m1 | | illegal/main.rs:62:17:62:24 | ...::S | illegal/main.rs:2:5:2:15 | struct S | | illegal/main.rs:64:13:64:17 | super | illegal/main.rs:1:1:71:1 | mod m1 | From 4ef18ca76b0a2a42e74e55bb6aa8fb8891722c20 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 30 Apr 2025 13:45:23 +0200 Subject: [PATCH 3/4] Rust: Also check visibility in method call resolution --- .../codeql/rust/internal/PathResolution.qll | 105 ++++++++++-------- .../codeql/rust/internal/TypeInference.qll | 6 +- .../path-resolution/illegal/main.rs | 4 +- 3 files changed, 65 insertions(+), 50 deletions(-) diff --git a/rust/ql/lib/codeql/rust/internal/PathResolution.qll b/rust/ql/lib/codeql/rust/internal/PathResolution.qll index cfb821adbfbd..d795b05bed34 100644 --- a/rust/ql/lib/codeql/rust/internal/PathResolution.qll +++ b/rust/ql/lib/codeql/rust/internal/PathResolution.qll @@ -1153,7 +1153,7 @@ private predicate pathUsesNamespace(Path p, Namespace n) { } pragma[nomagic] -private ItemNode resolvePath1(RelevantPath path) { +private ItemNode resolvePathCand(AstNode path) { exists(Namespace ns | result = resolvePath0(path, ns) | pathUsesNamespace(path, ns) or @@ -1162,59 +1162,70 @@ private ItemNode resolvePath1(RelevantPath path) { ) } -pragma[nomagic] -private ItemNode resolvePathPrivate( - RelevantPath path, ModuleLikeNode itemParent, ModuleLikeNode pathParent -) { - not path.requiresExtractorWorkaround() and - result = resolvePath1(path) and - result.isPrivate() and - ( - pathParent.getADescendant() = path - or - pathParent = any(ItemNode mid | path = mid.getADescendant()).getImmediateParentModule() - ) and - ( - itemParent = result.getVisibilityParent().getImmediateParentModule() - or - not result.hasVisibilityParent() and - itemParent = result.getImmediateParentModule() - ) -} +/** Gets an item that `n` may resolve to, not taking visibility into account. */ +signature ItemNode resolveCandidateSig(AstNode n); -pragma[nomagic] -private predicate isItemParent(ModuleLikeNode itemParent) { - exists(resolvePathPrivate(_, itemParent, _)) -} +/** Provides the predicate `resolve` for resolving items while taking visibility into account. */ +module ResolveWithVisibility { + pragma[nomagic] + private ItemNode resolvePathPrivate( + AstNode n, ModuleLikeNode itemParent, ModuleLikeNode pathParent + ) { + not n.(RelevantPath).requiresExtractorWorkaround() and + result = resolvePrivateCandidate(n) and + result.isPrivate() and + ( + pathParent.getADescendant() = n + or + pathParent = any(ItemNode mid | n = mid.getADescendant()).getImmediateParentModule() + ) and + ( + itemParent = result.getVisibilityParent().getImmediateParentModule() + or + not result.hasVisibilityParent() and + itemParent = result.getImmediateParentModule() + ) + } -/** - * Gets a module that has access to private items defined inside `itemParent`. - * - * According to [The Rust Reference][1] this is either `itemParent` itself or any - * descendant of `itemParent`. - * - * [1]: https://doc.rust-lang.org/reference/visibility-and-privacy.html#r-vis.access - */ -pragma[nomagic] -private ModuleLikeNode getAPrivateVisibleModule(ModuleLikeNode itemParent) { - isItemParent(itemParent) and - result.getImmediateParentModule*() = itemParent + pragma[nomagic] + private predicate isItemParent(ModuleLikeNode itemParent) { + exists(resolvePathPrivate(_, itemParent, _)) + } + + /** + * Gets a module that has access to private items defined inside `itemParent`. + * + * According to [The Rust Reference][1] this is either `itemParent` itself or any + * descendant of `itemParent`. + * + * [1]: https://doc.rust-lang.org/reference/visibility-and-privacy.html#r-vis.access + */ + pragma[nomagic] + private ModuleLikeNode getAPrivateVisibleModule(ModuleLikeNode itemParent) { + isItemParent(itemParent) and + result.getImmediateParentModule*() = itemParent + } + + /** Gets an item that `n` may resolve to, taking visibility into account. */ + ItemNode resolve(AstNode n) { + result = resolvePrivateCandidate(n) and + ( + result.isPublic() + or + n.(RelevantPath).requiresExtractorWorkaround() + ) + or + exists(ModuleLikeNode itemParent, ModuleLikeNode pathParent | + result = resolvePathPrivate(n, itemParent, pathParent) and + pathParent = getAPrivateVisibleModule(itemParent) + ) + } } /** Gets the item that `path` resolves to, if any. */ cached ItemNode resolvePath(RelevantPath path) { - result = resolvePath1(path) and - ( - result.isPublic() - or - path.requiresExtractorWorkaround() - ) - or - exists(ModuleLikeNode itemParent, ModuleLikeNode pathParent | - result = resolvePathPrivate(path, itemParent, pathParent) and - pathParent = getAPrivateVisibleModule(itemParent) - ) + result = ResolveWithVisibility::resolve(path) } pragma[nomagic] diff --git a/rust/ql/lib/codeql/rust/internal/TypeInference.qll b/rust/ql/lib/codeql/rust/internal/TypeInference.qll index 2fae9ef1f5b8..fa6accbcd071 100644 --- a/rust/ql/lib/codeql/rust/internal/TypeInference.qll +++ b/rust/ql/lib/codeql/rust/internal/TypeInference.qll @@ -913,12 +913,16 @@ private module Cached { name = mce.getIdentifier().getText() } + private ItemNode resolveMethodCallExprCand(AstNode mce) { + exists(string name | result = getMethodCallExprLookupType(mce, name).getMethod(name)) + } + /** * Gets a method that the method call `mce` resolves to, if any. */ cached Function resolveMethodCallExpr(MethodCallExpr mce) { - exists(string name | result = getMethodCallExprLookupType(mce, name).getMethod(name)) + result = ResolveWithVisibility::resolve(mce) } pragma[nomagic] diff --git a/rust/ql/test/library-tests/path-resolution/illegal/main.rs b/rust/ql/test/library-tests/path-resolution/illegal/main.rs index c02f4cc9bf82..e7b8ac46e08b 100644 --- a/rust/ql/test/library-tests/path-resolution/illegal/main.rs +++ b/rust/ql/test/library-tests/path-resolution/illegal/main.rs @@ -47,7 +47,7 @@ mod m1 { pub fn f() { println!("m1::nested2::f"); super::S(). // $ item=I1 - f(); // $ SPURIOUS: item=I4 (private) + f(); // illegal: private super::S::f( // illegal: private super::S() // $ item=I1 ); @@ -62,7 +62,7 @@ mod m1 { super::S() // $ item=I1 ); super::S(). // $ item=I1 - f2(); // $ SPURIOUS: item=I7 (private) + f2(); // illegal: private super::S::f2( super::S() // $ item=I1 ); // illegal: private From ddf49d7298eb3b4bab8da5eaf3d522ebcbe555f3 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Wed, 30 Apr 2025 14:32:50 +0200 Subject: [PATCH 4/4] Rust: Accept test changes --- .../PathResolutionConsistency.expected | 3 -- .../PathResolutionConsistency.expected | 3 -- .../ExtractionConsistency.expected | 2 + .../PathResolutionConsistency.expected | 41 +++++++++++++++++++ 4 files changed, 43 insertions(+), 6 deletions(-) delete mode 100644 rust/ql/test/extractor-tests/canonical_path/CONSISTENCY/PathResolutionConsistency.expected delete mode 100644 rust/ql/test/extractor-tests/canonical_path_disabled/CONSISTENCY/PathResolutionConsistency.expected create mode 100644 rust/ql/test/library-tests/path-resolution/CONSISTENCY/ExtractionConsistency.expected create mode 100644 rust/ql/test/query-tests/security/CWE-022/CONSISTENCY/PathResolutionConsistency.expected diff --git a/rust/ql/test/extractor-tests/canonical_path/CONSISTENCY/PathResolutionConsistency.expected b/rust/ql/test/extractor-tests/canonical_path/CONSISTENCY/PathResolutionConsistency.expected deleted file mode 100644 index fbc771e88519..000000000000 --- a/rust/ql/test/extractor-tests/canonical_path/CONSISTENCY/PathResolutionConsistency.expected +++ /dev/null @@ -1,3 +0,0 @@ -multipleMethodCallTargets -| regular.rs:29:5:29:9 | s.g() | anonymous.rs:15:9:15:22 | fn g | -| regular.rs:29:5:29:9 | s.g() | regular.rs:13:5:13:18 | fn g | diff --git a/rust/ql/test/extractor-tests/canonical_path_disabled/CONSISTENCY/PathResolutionConsistency.expected b/rust/ql/test/extractor-tests/canonical_path_disabled/CONSISTENCY/PathResolutionConsistency.expected deleted file mode 100644 index 849d19acbf0e..000000000000 --- a/rust/ql/test/extractor-tests/canonical_path_disabled/CONSISTENCY/PathResolutionConsistency.expected +++ /dev/null @@ -1,3 +0,0 @@ -multipleMethodCallTargets -| regular.rs:32:5:32:9 | s.g() | anonymous.rs:18:9:18:22 | fn g | -| regular.rs:32:5:32:9 | s.g() | regular.rs:16:5:16:18 | fn g | diff --git a/rust/ql/test/library-tests/path-resolution/CONSISTENCY/ExtractionConsistency.expected b/rust/ql/test/library-tests/path-resolution/CONSISTENCY/ExtractionConsistency.expected new file mode 100644 index 000000000000..e6035b443645 --- /dev/null +++ b/rust/ql/test/library-tests/path-resolution/CONSISTENCY/ExtractionConsistency.expected @@ -0,0 +1,2 @@ +extractionWarning +| illegal/main.rs:1:1:1:1 | semantic analyzer unavailable (not included as a module) | diff --git a/rust/ql/test/query-tests/security/CWE-022/CONSISTENCY/PathResolutionConsistency.expected b/rust/ql/test/query-tests/security/CWE-022/CONSISTENCY/PathResolutionConsistency.expected new file mode 100644 index 000000000000..03a2899da095 --- /dev/null +++ b/rust/ql/test/query-tests/security/CWE-022/CONSISTENCY/PathResolutionConsistency.expected @@ -0,0 +1,41 @@ +multiplePathResolutions +| src/main.rs:8:21:8:33 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:8:21:8:33 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:8:21:8:33 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:8:21:8:33 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:8:21:8:33 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:19:21:19:33 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:19:21:19:33 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:19:21:19:33 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:19:21:19:33 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:19:21:19:33 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:25:23:25:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:25:23:25:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:25:23:25:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:25:23:25:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:25:23:25:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:26:38:26:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:26:38:26:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:26:38:26:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:26:38:26:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:26:38:26:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:39:23:39:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:39:23:39:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:39:23:39:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:39:23:39:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:39:23:39:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:40:38:40:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:40:38:40:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:40:38:40:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:40:38:40:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:40:38:40:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:52:23:52:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:52:23:52:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:52:23:52:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:52:23:52:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:52:23:52:35 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:53:38:53:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:53:38:53:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:53:38:53:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:53:38:53:50 | ...::from | file://:0:0:0:0 | fn from | +| src/main.rs:53:38:53:50 | ...::from | file://:0:0:0:0 | fn from |