Skip to content

Commit 5888ed3

Browse files
committed
Rust: Do not dispatch to all implementations when trait target is accurate
1 parent 59ce721 commit 5888ed3

File tree

6 files changed

+28
-22
lines changed

6 files changed

+28
-22
lines changed

rust/ql/lib/codeql/rust/elements/internal/CallImpl.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ module Impl {
6666
}
6767

6868
/** Gets the resolved target of this call, if any. */
69-
Function getStaticTarget() { result = TypeInference::resolveCallTarget(this) }
69+
Function getStaticTarget() { result = TypeInference::resolveCallTarget(this, _) }
7070

7171
/** Gets the name of the function called, if any. */
7272
string getTargetName() { result = this.getStaticTarget().getName().getText() }
@@ -79,9 +79,9 @@ module Impl {
7979
Function getARuntimeTarget() {
8080
result.hasImplementation() and
8181
(
82-
result = this.getStaticTarget()
82+
result = TypeInference::resolveCallTarget(this, _)
8383
or
84-
result.implements(this.getStaticTarget())
84+
result.implements(TypeInference::resolveCallTarget(this, true))
8585
)
8686
}
8787
}

rust/ql/lib/codeql/rust/elements/internal/InvocationExprImpl.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,6 @@ module Impl {
9494
}
9595

9696
/** Gets the resolved target (function or tuple struct/variant), if any. */
97-
Addressable getResolvedTarget() { result = TypeInference::resolveCallTarget(this) }
97+
Addressable getResolvedTarget() { result = TypeInference::resolveCallTarget(this, _) }
9898
}
9999
}

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

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3522,12 +3522,27 @@ private module Cached {
35223522
any(MethodResolution::MethodCall mc).argumentHasImplicitBorrow(n)
35233523
}
35243524

3525-
/** Gets an item (function or tuple struct/variant) that `call` resolves to, if any. */
3525+
/**
3526+
* Gets an item (function or tuple struct/variant) that `call` resolves to, if
3527+
* any.
3528+
*
3529+
* The parameter `dispatch` is `true` if and only if the resolved target is a
3530+
* trait item because the a precise target could not be determined from the
3531+
* types (for instance in the presence of generics or `dyn` types)
3532+
*/
35263533
cached
3527-
Addressable resolveCallTarget(Expr call) {
3528-
result = call.(MethodResolution::MethodCall).resolveCallTarget(_, _, _)
3534+
Addressable resolveCallTarget(InvocationExpr call, boolean dispatch) {
3535+
dispatch = false and
3536+
result = call.(NonMethodResolution::NonMethodCall).resolveCallTargetViaPathResolution()
35293537
or
3530-
result = call.(NonMethodResolution::NonMethodCall).resolveCallTarget()
3538+
exists(ImplOrTraitItemNode i |
3539+
i instanceof TraitItemNode and dispatch = true
3540+
or
3541+
i instanceof ImplItemNode and dispatch = false
3542+
|
3543+
result = call.(MethodResolution::MethodCall).resolveCallTarget(i, _, _) or
3544+
result = call.(NonMethodResolution::NonMethodCall).resolveCallTargetViaTypeInference(i)
3545+
)
35313546
}
35323547

35333548
/**
@@ -3668,9 +3683,9 @@ private module Debug {
36683683
result = inferType(n, path)
36693684
}
36703685

3671-
Addressable debugResolveCallTarget(InvocationExpr c) {
3686+
Addressable debugResolveCallTarget(InvocationExpr c, boolean dispatch) {
36723687
c = getRelevantLocatable() and
3673-
result = resolveCallTarget(c)
3688+
result = resolveCallTarget(c, dispatch)
36743689
}
36753690

36763691
predicate debugConditionSatisfiesConstraint(

rust/ql/test/library-tests/dataflow/global/inline-flow.expected

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -194,11 +194,8 @@ edges
194194
| main.rs:351:13:351:21 | source(...) | main.rs:350:33:352:9 | { ... } | provenance | |
195195
| main.rs:358:37:360:9 | { ... } | main.rs:347:13:347:29 | self.get_number() | provenance | |
196196
| main.rs:359:13:359:21 | source(...) | main.rs:358:37:360:9 | { ... } | provenance | |
197-
| main.rs:370:44:372:9 | { ... } | main.rs:383:18:383:38 | t.get_double_number() | provenance | |
198-
| main.rs:370:44:372:9 | { ... } | main.rs:387:18:387:50 | ...::get_double_number(...) | provenance | |
199197
| main.rs:370:44:372:9 | { ... } | main.rs:395:18:395:38 | i.get_double_number() | provenance | |
200198
| main.rs:371:13:371:22 | source(...) | main.rs:370:44:372:9 | { ... } | provenance | |
201-
| main.rs:374:33:376:9 | { ... } | main.rs:391:18:391:37 | ...::get_default(...) | provenance | |
202199
| main.rs:374:33:376:9 | { ... } | main.rs:398:18:398:41 | ...::get_default(...) | provenance | |
203200
| main.rs:375:13:375:21 | source(...) | main.rs:374:33:376:9 | { ... } | provenance | |
204201
| main.rs:383:13:383:14 | n1 | main.rs:384:14:384:15 | n1 | provenance | |
@@ -492,10 +489,7 @@ testFailures
492489
| main.rs:327:14:327:14 | c | main.rs:326:17:326:25 | source(...) | main.rs:327:14:327:14 | c | $@ | main.rs:326:17:326:25 | source(...) | source(...) |
493490
| main.rs:335:10:335:10 | a | main.rs:316:13:316:21 | source(...) | main.rs:335:10:335:10 | a | $@ | main.rs:316:13:316:21 | source(...) | source(...) |
494491
| main.rs:384:14:384:15 | n1 | main.rs:359:13:359:21 | source(...) | main.rs:384:14:384:15 | n1 | $@ | main.rs:359:13:359:21 | source(...) | source(...) |
495-
| main.rs:384:14:384:15 | n1 | main.rs:371:13:371:22 | source(...) | main.rs:384:14:384:15 | n1 | $@ | main.rs:371:13:371:22 | source(...) | source(...) |
496492
| main.rs:388:14:388:15 | n2 | main.rs:359:13:359:21 | source(...) | main.rs:388:14:388:15 | n2 | $@ | main.rs:359:13:359:21 | source(...) | source(...) |
497-
| main.rs:388:14:388:15 | n2 | main.rs:371:13:371:22 | source(...) | main.rs:388:14:388:15 | n2 | $@ | main.rs:371:13:371:22 | source(...) | source(...) |
498493
| main.rs:392:14:392:15 | n3 | main.rs:351:13:351:21 | source(...) | main.rs:392:14:392:15 | n3 | $@ | main.rs:351:13:351:21 | source(...) | source(...) |
499-
| main.rs:392:14:392:15 | n3 | main.rs:375:13:375:21 | source(...) | main.rs:392:14:392:15 | n3 | $@ | main.rs:375:13:375:21 | source(...) | source(...) |
500494
| main.rs:396:14:396:15 | n4 | main.rs:371:13:371:22 | source(...) | main.rs:396:14:396:15 | n4 | $@ | main.rs:371:13:371:22 | source(...) | source(...) |
501495
| main.rs:399:14:399:15 | n5 | main.rs:375:13:375:21 | source(...) | main.rs:399:14:399:15 | n5 | $@ | main.rs:375:13:375:21 | source(...) | source(...) |

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -381,15 +381,15 @@ mod not_trait_dispatch {
381381

382382
// This call is to the default method implementation.
383383
let n1 = t.get_double_number();
384-
sink(n1); // $ hasTaintFlow=3 SPURIOUS: hasValueFlow=44
384+
sink(n1); // $ hasTaintFlow=3
385385

386386
// This call is to the default method implementation.
387387
let n2 = HasNumbers::get_double_number(&t);
388-
sink(n2); // $ hasTaintFlow=3 SPURIOUS: hasValueFlow=44
388+
sink(n2); // $ hasTaintFlow=3
389389

390390
// This call is to the default function implementation.
391391
let n3 = Three::get_default();
392-
sink(n3); // $ hasValueFlow=0 SPURIOUS: hasValueFlow=1
392+
sink(n3); // $ hasValueFlow=0
393393

394394
let i = TwentyTwo;
395395
let n4 = i.get_double_number();

rust/ql/test/library-tests/dataflow/global/viableCallable.expected

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,10 @@
112112
| main.rs:371:13:371:22 | source(...) | main.rs:1:1:3:1 | fn source |
113113
| main.rs:375:13:375:21 | source(...) | main.rs:1:1:3:1 | fn source |
114114
| main.rs:383:18:383:38 | t.get_double_number() | main.rs:346:9:348:9 | fn get_double_number |
115-
| main.rs:383:18:383:38 | t.get_double_number() | main.rs:370:9:372:9 | fn get_double_number |
116115
| main.rs:384:9:384:16 | sink(...) | main.rs:5:1:7:1 | fn sink |
117116
| main.rs:387:18:387:50 | ...::get_double_number(...) | main.rs:346:9:348:9 | fn get_double_number |
118-
| main.rs:387:18:387:50 | ...::get_double_number(...) | main.rs:370:9:372:9 | fn get_double_number |
119117
| main.rs:388:9:388:16 | sink(...) | main.rs:5:1:7:1 | fn sink |
120118
| main.rs:391:18:391:37 | ...::get_default(...) | main.rs:350:9:352:9 | fn get_default |
121-
| main.rs:391:18:391:37 | ...::get_default(...) | main.rs:374:9:376:9 | fn get_default |
122119
| main.rs:392:9:392:16 | sink(...) | main.rs:5:1:7:1 | fn sink |
123120
| main.rs:395:18:395:38 | i.get_double_number() | main.rs:370:9:372:9 | fn get_double_number |
124121
| main.rs:396:9:396:16 | sink(...) | main.rs:5:1:7:1 | fn sink |

0 commit comments

Comments
 (0)