Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions rust/ql/lib/codeql/rust/internal/PathResolution.qll
Original file line number Diff line number Diff line change
Expand Up @@ -874,7 +874,12 @@ final class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
*/
predicate isBlanketImplementation() { exists(this.getBlanketImplementationTypeParam()) }

override predicate hasCanonicalPath(Crate c) { this.resolveSelfTy().hasCanonicalPathPrefix(c) }
override predicate hasCanonicalPath(Crate c) {
this.resolveSelfTy().hasCanonicalPathPrefix(c)
or
this.isBlanketImplementation() and
c.getASourceFile().getFile() = this.getFile()
}

/**
* Holds if `(c1, c2)` forms a pair of crates for the type and trait
Expand Down Expand Up @@ -920,7 +925,12 @@ final class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
result = "<"
or
i = 1 and
result = this.getSelfCanonicalPath(c)
(
result = this.getSelfCanonicalPath(c)
or
this.isBlanketImplementation() and
result = "_"
)
or
if exists(this.getTraitPath())
then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
| regular.rs:13:5:13:18 | fn g | <test::regular::Struct>::g |
| regular.rs:16:1:18:1 | trait TraitWithBlanketImpl | test::regular::TraitWithBlanketImpl |
| regular.rs:17:5:17:16 | fn h | test::regular::TraitWithBlanketImpl::h |
| regular.rs:20:1:22:1 | impl TraitWithBlanketImpl for T { ... } | <_ as test::regular::TraitWithBlanketImpl> |
| regular.rs:21:5:21:18 | fn h | <_ as test::regular::TraitWithBlanketImpl>::h |
| regular.rs:24:1:24:12 | fn free | test::regular::free |
| regular.rs:26:1:32:1 | fn usage | test::regular::usage |
| regular.rs:34:1:38:1 | enum MyEnum | test::regular::MyEnum |
Expand Down
12 changes: 11 additions & 1 deletion rust/ql/test/library-tests/dataflow/models/external_file.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

pub fn generated_source(i: i64) -> i64 {
0
}
Expand Down Expand Up @@ -28,3 +27,14 @@ pub fn neutral_generated_summary(i: i64) -> i64 {
pub fn neutral_manual_summary(i: i64) -> i64 {
0
}

pub trait MyTrait2 {
fn flow_through2(i: i64) -> i64;
}

impl<T> MyTrait2 for T {
// inherits model from the trait function
fn flow_through2(i: i64) -> i64 {
0
}
}
45 changes: 31 additions & 14 deletions rust/ql/test/library-tests/dataflow/models/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ fn test_set_var_field() {
match e1 {
MyFieldEnum::C { field_c: i } => sink(i),
MyFieldEnum::D { field_d: i } => sink(i), // $ hasValueFlow=5
MyFieldEnum::E { field_e: o } => ()
MyFieldEnum::E { field_e: o } => (),
}
}

Expand Down Expand Up @@ -258,18 +258,17 @@ fn test_enum_source() {
match s {
MyFieldEnum::C { field_c: i } => sink(i),
MyFieldEnum::D { field_d: i } => sink(i), // $ hasValueFlow=12
MyFieldEnum::E { field_e: o } => ()
MyFieldEnum::E { field_e: o } => (),
}

let s = enum_source_nested(13);
match s {
MyFieldEnum::C { field_c: i } => sink(i),
MyFieldEnum::D { field_d: i } => sink(i),
MyFieldEnum::E { field_e: o } =>
{
MyFieldEnum::E { field_e: o } => {
match o {
Some(i) => sink(i), // $ hasValueFlow=13
None => ()
None => (),
}
}
}
Expand All @@ -281,13 +280,13 @@ fn test_enum_method_source() {
match s {
MyFieldEnum::C { field_c: i } => sink(i), // $ hasValueFlow=13
MyFieldEnum::D { field_d: i } => sink(i),
MyFieldEnum::E { field_e: o } => ()
MyFieldEnum::E { field_e: o } => (),
}
}

mod source_into_function {
use crate::MyFieldEnum;
use super::sink;
use crate::MyFieldEnum;

// has a source model
fn pass_source<A>(_i: i64, f: impl FnOnce(i64) -> A) -> A {
Expand Down Expand Up @@ -320,11 +319,10 @@ mod source_into_function {
match e {
MyFieldEnum::C { field_c: i } => sink(i),
MyFieldEnum::D { field_d: i } => sink(i),
MyFieldEnum::E { field_e: o } =>
{
MyFieldEnum::E { field_e: o } => {
match o {
Some(i) => sink(i), // $ hasValueFlow=5
None => ()
None => (),
}
}
}
Expand All @@ -333,22 +331,24 @@ mod source_into_function {
}

mod sink_out_of_function {
use crate::MyFieldEnum;
use super::source;
use crate::MyFieldEnum;

// has a sink model
fn pass_sink(f: impl FnOnce(()) -> i64) { }
fn pass_sink(f: impl FnOnce(()) -> i64) {}

// has a sink model
fn pass_sink_nested(f: impl FnOnce(()) -> MyFieldEnum) { }
fn pass_sink_nested(f: impl FnOnce(()) -> MyFieldEnum) {}

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

let b = |_a| {
let s = source(2);
MyFieldEnum::E { field_e: Option::Some(s) }
MyFieldEnum::E {
field_e: Option::Some(s),
}
};
pass_sink_nested(b); // $ hasValueFlow=2
}
Expand Down Expand Up @@ -460,6 +460,17 @@ impl Ord for MyStruct2 {
}
}

trait MyTrait3 {
fn flow_through3(i: i64) -> i64;
}

impl<T> MyTrait3 for T {
// has an explicit model
fn flow_through3(i: i64) -> i64 {
0
}
}

fn test_trait_model<T: Ord>(x: T) {
let x1 = source(20).max(0);
sink(x1); // $ hasValueFlow=20
Expand Down Expand Up @@ -488,6 +499,12 @@ fn test_trait_model<T: Ord>(x: T) {

let x7 = (source(28) as i32) < 1;
sink(x7);

let x8 = <()>::flow_through2(source(29));
sink(x8); // $ hasValueFlow=29

let x9 = <()>::flow_through3(source(30));
sink(x9); // $ hasValueFlow=30
}

mod external_file;
Expand Down
Loading
Loading