Skip to content

Commit 1370921

Browse files
committed
wip4
1 parent c7d4fc3 commit 1370921

File tree

5 files changed

+54
-62
lines changed

5 files changed

+54
-62
lines changed

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

Lines changed: 52 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,17 +1123,27 @@ private Function getMethodSuccessor(ItemNode item, string name, int arity) {
11231123
arity = result.getParamList().getNumberOfParams()
11241124
}
11251125

1126+
/**
1127+
* Holds if the type path `path` pointing to `type` is either empty, in which
1128+
* case `type` is not `&`, or `path` points to a type being referenced by `&`.
1129+
*/
1130+
bindingset[path, type]
1131+
predicate isRefStrippedRoot(TypePath path, Type type) {
1132+
path.isEmpty() and
1133+
type != TRefType()
1134+
or
1135+
path = TypePath::singleton(TRefTypeParameter()) and
1136+
exists(type)
1137+
}
1138+
11261139
/** Provides logic for resolving method calls. */
11271140
private module MethodCallResolution {
11281141
/**
11291142
* Holds if method `f` with the name `name` and the arity `arity` exists in
11301143
* `i`, and the type of the `self` parameter is `selfType`.
11311144
*
1132-
* TODO
1133-
* `rootType` is the root type of `selfType`, and `selfRootPath` points to
1134-
* `selfRootType` inside `selfType`, where `selfRootType` is either the type
1135-
* being implemented, when `i` is an `impl`, or the trait itself when `i` is
1136-
* a trait.
1145+
* `rootTypePath` points to the type `rootType` inside `selfType`, which is
1146+
* the (possibly `&`-stripped) root type of `selfType`.
11371147
*/
11381148
pragma[nomagic]
11391149
predicate methodInfo(
@@ -1144,12 +1154,7 @@ private module MethodCallResolution {
11441154
f = i.getASuccessor(name) and
11451155
arity = f.getParamList().getNumberOfParams() and
11461156
rootType = selfType.getTypeAt(rootTypePath) and
1147-
(
1148-
rootTypePath.isEmpty() and
1149-
rootType != TRefType()
1150-
or
1151-
rootTypePath = TypePath::singleton(TRefTypeParameter())
1152-
) and
1157+
isRefStrippedRoot(rootTypePath, rootType) and
11531158
selfType.appliesTo(f, pos, i) and
11541159
pos.isSelf() and
11551160
not i.(ImplItemNode).isBlanket()
@@ -1275,15 +1280,24 @@ private module MethodCallResolution {
12751280
}
12761281

12771282
/**
1278-
* Holds if the method inside `i` with matching name and arity can be ruled out
1279-
* as a candidate for the receiver type represented by `derefChainBorrow`.
1283+
* Holds if the candidate method inside `i` with matching name and arity can
1284+
* be ruled out as a target of this call, because the receiver type represented
1285+
* by `derefChainBorrow` is incompatible with the `self` parameter type.
12801286
*/
12811287
pragma[nomagic]
1282-
private predicate isNotCandidate(ImplOrTraitItemNode i, string derefChainBorrow) {
1288+
private predicate isIncompatibleCandidate(ImplOrTraitItemNode i, string derefChainBorrow) {
12831289
IsInstantiationOf<MethodCallCand, FunctionType, MethodCallReceiverIsInstantiationOfInput>::isNotInstantiationOf(MkMethodCallCand(this,
12841290
derefChainBorrow), i, _)
12851291
}
12861292

1293+
pragma[nomagic]
1294+
private Type getACandidateReceiverRootTypeAtSubstituteTraitBounds(
1295+
TypePath rootTypePath, string derefChainBorrow
1296+
) {
1297+
result = this.getACandidateReceiverTypeAtSubstituteTraitBounds(rootTypePath, derefChainBorrow) and
1298+
isRefStrippedRoot(rootTypePath, result)
1299+
}
1300+
12871301
/**
12881302
* Holds if the candidate receiver type represented by `derefChain` does not
12891303
* have a matching method target.
@@ -1294,16 +1308,10 @@ private module MethodCallResolution {
12941308
derefChainBorrow = derefChain + ";" and
12951309
not derefChain.matches("%.ref") and // no need to try a borrow if the last thing we did was a deref
12961310
rootType =
1297-
this.getACandidateReceiverTypeAtSubstituteTraitBounds(rootTypePath, derefChainBorrow) and
1298-
(
1299-
rootTypePath.isEmpty() and
1300-
rootType != TRefType()
1301-
or
1302-
rootTypePath = TypePath::singleton(TRefTypeParameter())
1303-
)
1311+
this.getACandidateReceiverRootTypeAtSubstituteTraitBounds(rootTypePath, derefChainBorrow)
13041312
|
13051313
forall(ImplOrTraitItemNode i | methodCallCandidate(this, i, _, rootTypePath, rootType) |
1306-
this.isNotCandidate(i, derefChainBorrow)
1314+
this.isIncompatibleCandidate(i, derefChainBorrow)
13071315
)
13081316
)
13091317
}
@@ -1318,11 +1326,10 @@ private module MethodCallResolution {
13181326
derefChainBorrow = derefChain + ";borrow" and
13191327
this.noCandidateReceiverTypeAtNoBorrow(derefChain) and
13201328
rootType =
1321-
this.getACandidateReceiverTypeAtSubstituteTraitBounds(rootTypePath, derefChainBorrow) and
1322-
rootTypePath = TypePath::singleton(TRefTypeParameter())
1329+
this.getACandidateReceiverRootTypeAtSubstituteTraitBounds(rootTypePath, derefChainBorrow)
13231330
|
13241331
forall(ImplOrTraitItemNode i | methodCallCandidate(this, i, _, rootTypePath, rootType) |
1325-
this.isNotCandidate(i, derefChainBorrow)
1332+
this.isIncompatibleCandidate(i, derefChainBorrow)
13261333
)
13271334
)
13281335
}
@@ -1463,12 +1470,7 @@ private module MethodCallResolution {
14631470
private predicate hasNoInherentTarget() {
14641471
exists(TypePath rootTypePath, Type rootType, string name, int arity |
14651472
this.isMethodCall(_, rootTypePath, rootType, name, arity) and
1466-
(
1467-
rootTypePath.isEmpty() and
1468-
rootType != TRefType()
1469-
or
1470-
rootTypePath = TypePath::singleton(TRefTypeParameter())
1471-
) and
1473+
isRefStrippedRoot(rootTypePath, rootType) and
14721474
forall(Impl i |
14731475
methodInfo(_, name, arity, i, _, rootTypePath, rootType) and
14741476
not i.hasTrait()
@@ -1663,8 +1665,8 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi
16631665
}
16641666

16651667
pragma[nomagic]
1666-
private Type getInferredSelfType(AccessEnvironment state, TypePath path) {
1667-
result = this.getACandidateReceiverTypeAt(path, state)
1668+
private Type getInferredSelfType(AccessEnvironment env, TypePath path) {
1669+
result = this.getACandidateReceiverTypeAt(path, env)
16681670
}
16691671

16701672
pragma[nomagic]
@@ -1689,16 +1691,16 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi
16891691
}
16901692

16911693
pragma[nomagic]
1692-
Type getInferredType(AccessEnvironment state, AccessPosition apos, TypePath path) {
1694+
Type getInferredType(AccessEnvironment env, AccessPosition apos, TypePath path) {
16931695
apos.asArgumentPosition().isSelf() and
1694-
result = this.getInferredSelfType(state, path)
1696+
result = this.getInferredSelfType(env, path)
16951697
or
16961698
result = this.getInferredNonSelfType(apos, path) and
1697-
exists(this.getTarget(state))
1699+
exists(this.getTarget(env))
16981700
}
16991701

1700-
Declaration getTarget(AccessEnvironment state) {
1701-
result = this.resolveCallTarget(state) // mutual recursion; resolving method calls requires resolving types and vice versa
1702+
Declaration getTarget(AccessEnvironment env) {
1703+
result = this.resolveCallTarget(env) // mutual recursion; resolving method calls requires resolving types and vice versa
17021704
}
17031705
}
17041706

@@ -1712,11 +1714,11 @@ private module MethodCallMatching = MatchingWithEnvironment<MethodCallMatchingIn
17121714
pragma[nomagic]
17131715
private Type inferMethodCallExprType0(
17141716
MethodCallMatchingInput::Access a, MethodCallMatchingInput::AccessPosition apos, AstNode n,
1715-
string state, TypePath path
1717+
string env, TypePath path
17161718
) {
17171719
exists(TypePath path0 |
17181720
n = a.getNodeAt(apos) and
1719-
result = MethodCallMatching::inferAccessType(a, state, apos, path0)
1721+
result = MethodCallMatching::inferAccessType(a, env, apos, path0)
17201722
|
17211723
if
17221724
// index expression `x[i]` desugars to `*x.index(i)`, so we must account for
@@ -1735,26 +1737,26 @@ private Type inferMethodCallExprType0(
17351737
pragma[nomagic]
17361738
private Type inferMethodCallExprType(AstNode n, TypePath path) {
17371739
exists(
1738-
MethodCallMatchingInput::Access a, MethodCallMatchingInput::AccessPosition apos, string state,
1740+
MethodCallMatchingInput::Access a, MethodCallMatchingInput::AccessPosition apos, string env,
17391741
TypePath path0
17401742
|
1741-
result = inferMethodCallExprType0(a, apos, n, state, path0)
1743+
result = inferMethodCallExprType0(a, apos, n, env, path0)
17421744
|
17431745
(
17441746
not apos.asArgumentPosition().isSelf()
17451747
or
1746-
state = ";"
1748+
env = ";"
17471749
) and
17481750
path = path0
17491751
or
17501752
// adjust for implicit deref
17511753
apos.asArgumentPosition().isSelf() and
1752-
state = ".ref;" and
1754+
env = ".ref;" and
17531755
path = TypePath::cons(TRefTypeParameter(), path0)
17541756
or
17551757
// adjust for implicit borrow
17561758
apos.asArgumentPosition().isSelf() and
1757-
state = ";borrow" and
1759+
env = ";borrow" and
17581760
path0.isCons(TRefTypeParameter(), path)
17591761
)
17601762
}
@@ -2314,18 +2316,13 @@ private Type inferOperationType(AstNode n, TypePath path) {
23142316
)
23152317
}
23162318

2317-
pragma[inline]
2318-
private Type inferRootTypeDeref(AstNode n) {
2319-
result = inferType(n) and
2320-
result != TRefType()
2321-
or
2322-
// for reference types, lookup members in the type being referenced
2323-
result = inferType(n, TypePath::singleton(TRefTypeParameter()))
2324-
}
2325-
23262319
pragma[nomagic]
23272320
private Type getFieldExprLookupType(FieldExpr fe, string name) {
2328-
result = inferRootTypeDeref(fe.getContainer()) and name = fe.getIdentifier().getText()
2321+
exists(TypePath path |
2322+
result = inferType(fe.getContainer(), path) and
2323+
name = fe.getIdentifier().getText() and
2324+
isRefStrippedRoot(path, result)
2325+
)
23292326
}
23302327

23312328
pragma[nomagic]
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
11
multipleCallTargets
2-
| main.rs:322:14:322:33 | ... .cmp(...) |
3-
| main.rs:334:9:334:28 | ... .cmp(...) |
42
| main.rs:362:14:362:30 | ... .lt(...) |

rust/ql/test/library-tests/dataflow/sources/CONSISTENCY/PathResolutionConsistency.expected

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ multipleCallTargets
1111
| test.rs:179:30:179:68 | ...::_print(...) |
1212
| test.rs:188:26:188:105 | ...::_print(...) |
1313
| test.rs:229:22:229:72 | ... .read_to_string(...) |
14-
| test.rs:639:26:639:43 | file1.chain(...) |
15-
| test.rs:647:26:647:40 | file1.take(...) |
1614
| test.rs:697:18:697:38 | ...::_print(...) |
1715
| test.rs:702:18:702:45 | ...::_print(...) |
1816
| test.rs:720:38:720:42 | ...::_print(...) |

rust/ql/test/library-tests/dataflow/sources/test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -638,15 +638,15 @@ async fn test_tokio_file() -> std::io::Result<()> {
638638
let file2 = tokio::fs::File::open("another_file.txt").await?; // $ Alert[rust/summary/taint-sources]
639639
let mut reader = file1.chain(file2);
640640
reader.read_to_string(&mut buffer).await?;
641-
sink(&buffer); // $ hasTaintFlow="file.txt" hasTaintFlow="another_file.txt"
641+
sink(&buffer); // $ MISSING: hasTaintFlow="file.txt" hasTaintFlow="another_file.txt" -- we cannot resolve the `chain` and `read_to_string` calls above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
642642
}
643643

644644
{
645645
let mut buffer = String::new();
646646
let file1 = tokio::fs::File::open("file.txt").await?; // $ Alert[rust/summary/taint-sources]
647647
let mut reader = file1.take(100);
648648
reader.read_to_string(&mut buffer).await?;
649-
sink(&buffer); // $ hasTaintFlow="file.txt"
649+
sink(&buffer); // $ MISSING: hasTaintFlow="file.txt" -- we cannot resolve the `take` and `read_to_string` calls above, which comes from `impl<R: AsyncRead + ?Sized> AsyncReadExt for R {}` in `async_read_ext.rs`
650650
}
651651

652652
Ok(())

rust/ql/test/library-tests/type-inference/CONSISTENCY/PathResolutionConsistency.expected

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ multipleCallTargets
55
| dereference.rs:184:17:184:30 | ... .foo() |
66
| dereference.rs:186:17:186:25 | S.bar(...) |
77
| dereference.rs:187:17:187:29 | S.bar(...) |
8-
| main.rs:1803:13:1803:63 | ... .partial_cmp(...) |
98
| main.rs:2318:9:2318:34 | ...::my_from2(...) |
109
| main.rs:2319:9:2319:33 | ...::my_from2(...) |
1110
| main.rs:2320:9:2320:38 | ...::my_from2(...) |

0 commit comments

Comments
 (0)