Rust: Data flow through trait methods#19881
Conversation
2ef6a9f to
5e79203
Compare
5e79203 to
8c24039
Compare
There was a problem hiding this comment.
Pull Request Overview
Enhance data-flow tracking by dispatching trait method calls to all implementations and by applying data-flow models to implementations without source code.
- Extend models to include
Ord::maxandPartialOrd::lttrait methods - Update tests to cover trait dispatch scenarios and adjust expectations
- Introduce QL predicates for runtime trait dispatch (
getARuntimeTarget,implements) and adjust DataFlowImpl to use them
Reviewed Changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| rust/ql/test/library-tests/dataflow/models/models.ext.yml | Add models for <_ as Ord>::max and <_ as PartialOrd>::lt |
| rust/ql/test/library-tests/dataflow/models/models.expected | Update expected summaries to include new trait models |
| rust/ql/test/library-tests/dataflow/models/main.rs | Add test_trait_model and trait implementations for Ord |
| rust/ql/test/library-tests/dataflow/global/main.rs | Introduce MyTrait, MyTrait2, and trait-dispatch tests |
| rust/ql/lib/codeql/rust/internal/PathResolution.qll | Add getAssocItem(name) helper |
| rust/ql/lib/codeql/rust/elements/internal/CallImpl.qll | Define getARuntimeTarget for dispatching to impls |
| rust/ql/lib/codeql/rust/elements/internal/AssocItemImpl.qll | Implement implements relation for associated items |
| rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll | Override hasProvenance to pick up summary models |
| rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll | Enhance viableCallable to consider runtime trait dispatch |
| rust/ql/.gitattributes | Remove generated marker for AssocItemImpl.qll |
| rust/ql/.generated.list | Remove AssocItemImpl.qll from generated list |
Comments suppressed due to low confidence (2)
rust/ql/test/library-tests/dataflow/global/main.rs:280
- [nitpick] Using a numeric suffix in the trait name (
MyTrait2) can be confusing; consider a more descriptive name or merge it into the existing trait to avoid ambiguity.
trait MyTrait2 {
rust/ql/lib/codeql/rust/elements/internal/CallImpl.qll:71
- [nitpick] Method name
getARuntimeTargetis a bit verbose and uses mixed-case acronym; consider renaming togetRuntimeTargetfor consistency with your naming conventions.
Function getARuntimeTarget() {
| @@ -404,10 +404,20 @@ module RustDataFlow implements InputSig<Location> { | |||
|
|
|||
| /** Gets a viable implementation of the target of the given `Call`. */ | |||
| DataFlowCallable viableCallable(DataFlowCall call) { | |||
There was a problem hiding this comment.
[nitpick] The viableCallable definition contains deeply nested exists and or expressions; extracting the trait-dispatch logic into a helper predicate could improve readability and maintenance.
geoffw0
left a comment
There was a problem hiding this comment.
LGTM.
I've started in the DCA run on a discussion of a couple of points (I think you've seen it), neither of them block merging this work.
| * `Field[core::option::Option::Some(0)]`. | ||
| * - `Field[i]`: the `i`th element of a tuple. | ||
| * - `Reference`: the referenced value. | ||
| * - `Future`: the value being computed asynchronously. |
This PR makes two improvements to data flow:
foo<T : Trait>(x : T) { x.trait_method() }, data flow will now dispatch to all possible implementations of the trait method, just like we do for virtual dispatch in OO languages like C# and Java.The first improvement is likely to result in some false positive flow, which we can address to some extent later by tracking types in data flow.