Skip to content

Commit 4bae300

Browse files
committed
wip
1 parent c77c3ec commit 4bae300

File tree

4 files changed

+45
-10
lines changed

4 files changed

+45
-10
lines changed

rust/ql/lib/codeql/rust/frameworks/stdlib/Stdlib.qll

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
private import rust
66
private import codeql.rust.Concepts
77
private import codeql.rust.dataflow.DataFlow
8+
private import codeql.rust.dataflow.FlowSummary
89
private import codeql.rust.internal.PathResolution
10+
private import codeql.rust.internal.typeinference.Type
11+
private import codeql.rust.internal.typeinference.TypeMention
912

1013
/**
1114
* A call to the `starts_with` method on a `Path`.
@@ -297,3 +300,28 @@ class Vec extends Struct {
297300
/** Gets the type parameter representing the element type. */
298301
TypeParam getElementTypeParam() { result = this.getGenericParamList().getTypeParam(0) }
299302
}
303+
304+
private class ReflexiveFrom extends SummarizedCallable::Range {
305+
ReflexiveFrom() {
306+
exists(ImplItemNode impl |
307+
impl.resolveTraitTy().(Trait).getCanonicalPath() = "core::convert::From" and
308+
this = impl.getAnAssocItem() and
309+
impl.isBlanketImplementation() and
310+
this.getParam(0)
311+
.getTypeRepr()
312+
.(TypeMention)
313+
.resolveType()
314+
.(TypeParamTypeParameter)
315+
.getTypeParam() = impl.getTypeParam(0)
316+
)
317+
}
318+
319+
override predicate propagatesFlow(
320+
string input, string output, boolean preservesValue, string model
321+
) {
322+
input = "Argument[0]" and
323+
output = "ReturnValue" and
324+
preservesValue = true and
325+
model = "ReflexiveFrom"
326+
}
327+
}

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

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,6 +1287,11 @@ private class BorrowKind extends TBorrowKind {
12871287
}
12881288
}
12891289

1290+
private predicate isNotConstrainedTypeParameter(Type t) {
1291+
not t instanceof TypeParameter or
1292+
t.(TypeParamTypeParameter).getTypeParam() = any(TypeParam tp | not exists(tp.getATypeBound()))
1293+
}
1294+
12901295
/**
12911296
* Provides logic for resolving calls to methods.
12921297
*
@@ -2383,9 +2388,8 @@ private module MethodResolution {
23832388
FunctionOverloading::functionResolutionDependsOnArgument(i, f, pos, path, t0) and
23842389
t.appliesTo(f, i, pos) and
23852390
// for now, we do not handle ambiguous targets when one of the types it iself
2386-
// a type parameter; we should be checking the constraints on that type parameter
2387-
// in this case
2388-
not t0 instanceof TypeParameter
2391+
// a constrained type parameter; we should be checking the constraints in this case
2392+
isNotConstrainedTypeParameter(t0)
23892393
)
23902394
}
23912395

@@ -2796,15 +2800,19 @@ private module NonMethodResolution {
27962800
}
27972801

27982802
pragma[nomagic]
2799-
predicate hasNoCompatibleNonBlanketTarget() {
2800-
not exists(this.resolveCallTargetViaPathResolution()) and
2803+
predicate hasNoCompatibleNonBlanketTargetViaTypeInference() {
28012804
forall(ImplOrTraitItemNode i, Function f |
28022805
this.(NonMethodArgsAreInstantiationsOfNonBlanketInput::Call).hasTargetCand(i, f)
28032806
|
28042807
NonMethodArgsAreInstantiationsOfNonBlanket::argsAreNotInstantiationsOf(this, i, f)
28052808
)
28062809
}
28072810

2811+
predicate hasNoCompatibleNonBlanketTarget() {
2812+
not exists(this.resolveCallTargetViaPathResolution()) and
2813+
this.hasNoCompatibleNonBlanketTargetViaTypeInference()
2814+
}
2815+
28082816
/**
28092817
* Gets the target of this call, which can be resolved using only path resolution.
28102818
*/
@@ -2910,9 +2918,8 @@ private module NonMethodResolution {
29102918
t.appliesTo(f, i, pos) and
29112919
exists(Type t0 |
29122920
// for now, we do not handle ambiguous targets when one of the types it iself
2913-
// a type parameter; we should be checking the constraints on that type parameter
2914-
// in this case
2915-
not t0 instanceof TypeParameter
2921+
// a constrained type parameter; we should be checking the constraints in this case
2922+
isNotConstrainedTypeParameter(t0)
29162923
|
29172924
FunctionOverloading::functionResolutionDependsOnArgument(i, f, pos, _, t0)
29182925
or

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ edges
303303
| main.rs:566:18:566:27 | source(...) | main.rs:566:9:566:9 | a | provenance | |
304304
| main.rs:569:10:569:10 | a | main.rs:569:10:569:17 | a.into() | provenance | MaD:4 |
305305
| main.rs:569:10:569:10 | a | main.rs:569:10:569:17 | a.into() | provenance | MaD:5 |
306-
| main.rs:570:20:570:20 | a | main.rs:570:10:570:21 | ...::from(...) | provenance | MaD:3 |
306+
| main.rs:570:20:570:20 | a | main.rs:570:10:570:21 | ...::from(...) | provenance | ReflexiveFrom |
307307
| main.rs:572:9:572:9 | b | main.rs:574:10:574:17 | b as i64 | provenance | |
308308
| main.rs:572:9:572:9 | b | main.rs:575:10:575:10 | b | provenance | |
309309
| main.rs:572:9:572:9 | b | main.rs:576:20:576:20 | b | provenance | |

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ fn conversions() {
567567

568568
sink(a as i64); // $ hasTaintFlow=50
569569
sink(a.into()); // $ SPURIOUS: hasTaintFlow=50 $ MISSING: hasValueFlow=50 -- it is not possible to define a value-preserving summary for `into` since it depends on which `from` function is called
570-
sink(i64::from(a)); // $ hasTaintFlow=50
570+
sink(i64::from(a)); // $ hasValueFlow=50
571571

572572
let b: i32 = source(51) as i32;
573573

0 commit comments

Comments
 (0)