Skip to content

Commit ec63c66

Browse files
authored
Merge pull request #22405 from hvitved/rust/canonical-path-blanket
Rust: Canonical paths for blanket implementations
2 parents 782f1fc + b12b1d0 commit ec63c66

6 files changed

Lines changed: 409 additions & 334 deletions

File tree

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -874,7 +874,12 @@ final class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
874874
*/
875875
predicate isBlanketImplementation() { exists(this.getBlanketImplementationTypeParam()) }
876876

877-
override predicate hasCanonicalPath(Crate c) { this.resolveSelfTy().hasCanonicalPathPrefix(c) }
877+
override predicate hasCanonicalPath(Crate c) {
878+
this.resolveSelfTy().hasCanonicalPathPrefix(c)
879+
or
880+
this.isBlanketImplementation() and
881+
c.getASourceFile().getFile() = this.getFile()
882+
}
878883

879884
/**
880885
* Holds if `(c1, c2)` forms a pair of crates for the type and trait
@@ -920,7 +925,12 @@ final class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
920925
result = "<"
921926
or
922927
i = 1 and
923-
result = this.getSelfCanonicalPath(c)
928+
(
929+
result = this.getSelfCanonicalPath(c)
930+
or
931+
this.isBlanketImplementation() and
932+
result = "_"
933+
)
924934
or
925935
if exists(this.getTraitPath())
926936
then

rust/ql/test/extractor-tests/canonical_path/canonical_paths.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
| regular.rs:13:5:13:18 | fn g | <test::regular::Struct>::g |
1616
| regular.rs:16:1:18:1 | trait TraitWithBlanketImpl | test::regular::TraitWithBlanketImpl |
1717
| regular.rs:17:5:17:16 | fn h | test::regular::TraitWithBlanketImpl::h |
18+
| regular.rs:20:1:22:1 | impl TraitWithBlanketImpl for T { ... } | <_ as test::regular::TraitWithBlanketImpl> |
19+
| regular.rs:21:5:21:18 | fn h | <_ as test::regular::TraitWithBlanketImpl>::h |
1820
| regular.rs:24:1:24:12 | fn free | test::regular::free |
1921
| regular.rs:26:1:32:1 | fn usage | test::regular::usage |
2022
| regular.rs:34:1:38:1 | enum MyEnum | test::regular::MyEnum |

rust/ql/test/library-tests/dataflow/models/external_file.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
pub fn generated_source(i: i64) -> i64 {
32
0
43
}
@@ -28,3 +27,14 @@ pub fn neutral_generated_summary(i: i64) -> i64 {
2827
pub fn neutral_manual_summary(i: i64) -> i64 {
2928
0
3029
}
30+
31+
pub trait MyTrait2 {
32+
fn flow_through2(i: i64) -> i64;
33+
}
34+
35+
impl<T> MyTrait2 for T {
36+
// inherits model from the trait function
37+
fn flow_through2(i: i64) -> i64 {
38+
0
39+
}
40+
}

rust/ql/test/library-tests/dataflow/models/main.rs

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ fn test_set_var_field() {
102102
match e1 {
103103
MyFieldEnum::C { field_c: i } => sink(i),
104104
MyFieldEnum::D { field_d: i } => sink(i), // $ hasValueFlow=5
105-
MyFieldEnum::E { field_e: o } => ()
105+
MyFieldEnum::E { field_e: o } => (),
106106
}
107107
}
108108

@@ -258,18 +258,17 @@ fn test_enum_source() {
258258
match s {
259259
MyFieldEnum::C { field_c: i } => sink(i),
260260
MyFieldEnum::D { field_d: i } => sink(i), // $ hasValueFlow=12
261-
MyFieldEnum::E { field_e: o } => ()
261+
MyFieldEnum::E { field_e: o } => (),
262262
}
263263

264264
let s = enum_source_nested(13);
265265
match s {
266266
MyFieldEnum::C { field_c: i } => sink(i),
267267
MyFieldEnum::D { field_d: i } => sink(i),
268-
MyFieldEnum::E { field_e: o } =>
269-
{
268+
MyFieldEnum::E { field_e: o } => {
270269
match o {
271270
Some(i) => sink(i), // $ hasValueFlow=13
272-
None => ()
271+
None => (),
273272
}
274273
}
275274
}
@@ -281,13 +280,13 @@ fn test_enum_method_source() {
281280
match s {
282281
MyFieldEnum::C { field_c: i } => sink(i), // $ hasValueFlow=13
283282
MyFieldEnum::D { field_d: i } => sink(i),
284-
MyFieldEnum::E { field_e: o } => ()
283+
MyFieldEnum::E { field_e: o } => (),
285284
}
286285
}
287286

288287
mod source_into_function {
289-
use crate::MyFieldEnum;
290288
use super::sink;
289+
use crate::MyFieldEnum;
291290

292291
// has a source model
293292
fn pass_source<A>(_i: i64, f: impl FnOnce(i64) -> A) -> A {
@@ -320,11 +319,10 @@ mod source_into_function {
320319
match e {
321320
MyFieldEnum::C { field_c: i } => sink(i),
322321
MyFieldEnum::D { field_d: i } => sink(i),
323-
MyFieldEnum::E { field_e: o } =>
324-
{
322+
MyFieldEnum::E { field_e: o } => {
325323
match o {
326324
Some(i) => sink(i), // $ hasValueFlow=5
327-
None => ()
325+
None => (),
328326
}
329327
}
330328
}
@@ -333,22 +331,24 @@ mod source_into_function {
333331
}
334332

335333
mod sink_out_of_function {
336-
use crate::MyFieldEnum;
337334
use super::source;
335+
use crate::MyFieldEnum;
338336

339337
// has a sink model
340-
fn pass_sink(f: impl FnOnce(()) -> i64) { }
338+
fn pass_sink(f: impl FnOnce(()) -> i64) {}
341339

342340
// has a sink model
343-
fn pass_sink_nested(f: impl FnOnce(()) -> MyFieldEnum) { }
341+
fn pass_sink_nested(f: impl FnOnce(()) -> MyFieldEnum) {}
344342

345343
fn test_sink_out_of_function() {
346344
let a = |a| source(1);
347345
pass_sink(a); // $ hasValueFlow=1
348346

349347
let b = |_a| {
350348
let s = source(2);
351-
MyFieldEnum::E { field_e: Option::Some(s) }
349+
MyFieldEnum::E {
350+
field_e: Option::Some(s),
351+
}
352352
};
353353
pass_sink_nested(b); // $ hasValueFlow=2
354354
}
@@ -460,6 +460,17 @@ impl Ord for MyStruct2 {
460460
}
461461
}
462462

463+
trait MyTrait3 {
464+
fn flow_through3(i: i64) -> i64;
465+
}
466+
467+
impl<T> MyTrait3 for T {
468+
// has an explicit model
469+
fn flow_through3(i: i64) -> i64 {
470+
0
471+
}
472+
}
473+
463474
fn test_trait_model<T: Ord>(x: T) {
464475
let x1 = source(20).max(0);
465476
sink(x1); // $ hasValueFlow=20
@@ -488,6 +499,12 @@ fn test_trait_model<T: Ord>(x: T) {
488499

489500
let x7 = (source(28) as i32) < 1;
490501
sink(x7);
502+
503+
let x8 = <()>::flow_through2(source(29));
504+
sink(x8); // $ hasValueFlow=29
505+
506+
let x9 = <()>::flow_through3(source(30));
507+
sink(x9); // $ hasValueFlow=30
491508
}
492509

493510
mod external_file;

0 commit comments

Comments
 (0)