Skip to content

Commit 61f14f0

Browse files
committed
Rust: Make SummarizedCallable extend Function instead of string
1 parent f3c5646 commit 61f14f0

File tree

26 files changed

+540
-2062
lines changed

26 files changed

+540
-2062
lines changed

rust/ql/lib/codeql/rust/dataflow/FlowSummary.qll

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,17 @@
22

33
private import rust
44
private import internal.FlowSummaryImpl as Impl
5-
private import codeql.rust.elements.internal.CallExprBaseImpl::Impl as CallExprBaseImpl
65

76
// import all instances below
87
private module Summaries {
98
private import codeql.rust.Frameworks
109
private import codeql.rust.dataflow.internal.ModelsAsData
1110
}
1211

13-
/** Provides the `Range` class used to define the extent of `LibraryCallable`. */
14-
module LibraryCallable {
15-
/** A callable defined in library code, identified by a unique string. */
16-
abstract class Range extends string {
17-
bindingset[this]
18-
Range() { any() }
19-
20-
/** Gets a call to this library callable. */
21-
CallExprBase getACall() {
22-
exists(Resolvable r, string crate |
23-
r = CallExprBaseImpl::getCallResolvable(result) and
24-
this = crate + r.getResolvedPath()
25-
|
26-
crate = r.getResolvedCrateOrigin() + "::_::"
27-
or
28-
not r.hasResolvedCrateOrigin() and
29-
crate = ""
30-
)
31-
}
32-
}
33-
}
34-
35-
final class LibraryCallable = LibraryCallable::Range;
36-
3712
/** Provides the `Range` class used to define the extent of `SummarizedCallable`. */
3813
module SummarizedCallable {
3914
/** A callable with a flow summary, identified by a unique string. */
40-
abstract class Range extends LibraryCallable::Range, Impl::Public::SummarizedCallable {
15+
abstract class Range extends Impl::Public::SummarizedCallable {
4116
bindingset[this]
4217
Range() { any() }
4318

rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,12 @@ final class DataFlowCallable extends TDataFlowCallable {
4343
/**
4444
* Gets the underlying library callable, if any.
4545
*/
46-
LibraryCallable asLibraryCallable() { this = TLibraryCallable(result) }
46+
SummarizedCallable asSummarizedCallable() { this = TSummarizedCallable(result) }
4747

4848
/** Gets a textual representation of this callable. */
49-
string toString() { result = [this.asCfgScope().toString(), this.asLibraryCallable().toString()] }
49+
string toString() {
50+
result = [this.asCfgScope().toString(), this.asSummarizedCallable().toString()]
51+
}
5052

5153
/** Gets the location of this callable. */
5254
Location getLocation() { result = this.asCfgScope().getLocation() }
@@ -67,12 +69,9 @@ final class DataFlowCall extends TDataFlowCall {
6769
}
6870

6971
DataFlowCallable getEnclosingCallable() {
70-
result = TCfgScope(this.asCallBaseExprCfgNode().getExpr().getEnclosingCfgScope())
72+
result.asCfgScope() = this.asCallBaseExprCfgNode().getExpr().getEnclosingCfgScope()
7173
or
72-
exists(FlowSummaryImpl::Public::SummarizedCallable c |
73-
this.isSummaryCall(c, _) and
74-
result = TLibraryCallable(c)
75-
)
74+
this.isSummaryCall(result.asSummarizedCallable(), _)
7675
}
7776

7877
string toString() {
@@ -434,9 +433,13 @@ module RustDataFlow implements InputSig<Location> {
434433

435434
/** Gets a viable implementation of the target of the given `Call`. */
436435
DataFlowCallable viableCallable(DataFlowCall call) {
437-
result.asCfgScope() = call.asCallBaseExprCfgNode().getCallExprBase().getStaticTarget()
438-
or
439-
result.asLibraryCallable().getACall() = call.asCallBaseExprCfgNode().getCallExprBase()
436+
exists(Callable target |
437+
target = call.asCallBaseExprCfgNode().getCallExprBase().getStaticTarget()
438+
|
439+
target = result.asCfgScope()
440+
or
441+
target = result.asSummarizedCallable()
442+
)
440443
}
441444

442445
/**
@@ -784,7 +787,7 @@ module RustDataFlow implements InputSig<Location> {
784787
predicate allowParameterReturnInSelf(ParameterNode p) {
785788
exists(DataFlowCallable c, ParameterPosition pos |
786789
p.isParameterOf(c, pos) and
787-
FlowSummaryImpl::Private::summaryAllowParameterReturnInSelf(c.asLibraryCallable(), pos)
790+
FlowSummaryImpl::Private::summaryAllowParameterReturnInSelf(c.asSummarizedCallable(), pos)
788791
)
789792
or
790793
VariableCapture::Flow::heuristicAllowInstanceParameterReturnInSelf(p.(ClosureParameterNode)
@@ -995,7 +998,7 @@ private module Cached {
995998
cached
996999
newtype TDataFlowCallable =
9971000
TCfgScope(CfgScope scope) or
998-
TLibraryCallable(LibraryCallable c)
1001+
TSummarizedCallable(SummarizedCallable c)
9991002

10001003
/** This is the local flow predicate that is exposed. */
10011004
cached

rust/ql/lib/codeql/rust/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module Input implements InputSig<Location, RustDataFlow> {
1313
private import codeql.rust.elements.internal.CallExprBaseImpl::Impl as CallExprBaseImpl
1414
private import codeql.rust.frameworks.stdlib.Stdlib
1515

16-
class SummarizedCallableBase = string;
16+
class SummarizedCallableBase = Function;
1717

1818
abstract private class SourceSinkBase extends AstNode {
1919
/** Gets the associated call. */
@@ -153,7 +153,7 @@ private import Make<Location, RustDataFlow, Input> as Impl
153153

154154
private module StepsInput implements Impl::Private::StepsInputSig {
155155
DataFlowCall getACall(Public::SummarizedCallable sc) {
156-
result.asCallBaseExprCfgNode().getCallExprBase() = sc.(LibraryCallable).getACall()
156+
result.asCallBaseExprCfgNode().getCallExprBase().getStaticTarget() = sc
157157
}
158158

159159
RustDataFlow::Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponent sc) {

rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ private import rust
4747
private import codeql.rust.dataflow.FlowSummary
4848
private import codeql.rust.dataflow.FlowSource
4949
private import codeql.rust.dataflow.FlowSink
50+
private import codeql.rust.elements.internal.CallExprBaseImpl::Impl as CallExprBaseImpl
5051

5152
/**
5253
* Holds if in a call to the function with canonical path `path`, defined in the
@@ -114,13 +115,30 @@ predicate interpretModelForTest(QlBuiltins::ExtensionId madId, string model) {
114115
)
115116
}
116117

118+
private predicate sdf(CallExprBase call, Function f) {
119+
CallExprBaseImpl::getCallResolvable(call).getResolvedPath() = "<crate::option::Option>::unwrap" and
120+
// CallExprBaseImpl::getCallResolvable(call).getResolvedCrateOrigin() = "lang:core" and
121+
f = call.getStaticTarget()
122+
}
123+
124+
private predicate sdf2(CallExprBase call) {
125+
CallExprBaseImpl::getCallResolvable(call).getResolvedPath() = "<crate::option::Option>::unwrap"
126+
// CallExprBaseImpl::getCallResolvable(call).getResolvedCrateOrigin() = "lang:core" and
127+
// f = call.getStaticTarget()
128+
}
129+
117130
private class SummarizedCallableFromModel extends SummarizedCallable::Range {
118131
private string crate;
119132
private string path;
120133

121134
SummarizedCallableFromModel() {
122135
summaryModel(crate, path, _, _, _, _, _) and
123-
this = crate + "::_::" + path
136+
exists(CallExprBase call, Resolvable r |
137+
call.getStaticTarget() = this and
138+
r = CallExprBaseImpl::getCallResolvable(call) and
139+
r.getResolvedPath() = path and
140+
r.getResolvedCrateOrigin() = crate
141+
)
124142
}
125143

126144
override predicate propagatesFlow(

rust/ql/lib/codeql/rust/dataflow/internal/Node.qll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ abstract class NodePublic extends TNode {
4444

4545
abstract class Node extends NodePublic {
4646
/** Gets the enclosing callable. */
47-
DataFlowCallable getEnclosingCallable() { result = TCfgScope(this.getCfgScope()) }
47+
DataFlowCallable getEnclosingCallable() { result.asCfgScope() = this.getCfgScope() }
4848

4949
/** Do not call: use `getEnclosingCallable()` instead. */
5050
abstract CfgScope getCfgScope();
@@ -102,9 +102,9 @@ class FlowSummaryNode extends Node, TFlowSummaryNode {
102102
}
103103

104104
override DataFlowCallable getEnclosingCallable() {
105-
result.asLibraryCallable() = this.getSummarizedCallable()
106-
or
107105
result.asCfgScope() = this.getCfgScope()
106+
or
107+
result.asSummarizedCallable() = this.getSummarizedCallable()
108108
}
109109

110110
override Location getLocation() {
@@ -195,7 +195,7 @@ final class SummaryParameterNode extends ParameterNode, FlowSummaryNode {
195195
}
196196

197197
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
198-
this.getSummarizedCallable() = c.asLibraryCallable() and pos = pos_
198+
this.getSummarizedCallable() = c.asSummarizedCallable() and pos = pos_
199199
}
200200
}
201201

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

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,8 @@ private import codeql.rust.dataflow.FlowSummary
66
/** A `clone` method. */
77
final class CloneCallable extends SummarizedCallable::Range {
88
CloneCallable() {
9-
// NOTE: The function target may not exist in the database, so we base this
10-
// on method calls.
11-
exists(MethodCallExpr c |
12-
c.getIdentifier().getText() = "clone" and
13-
c.getArgList().getNumberOfArgs() = 0 and
14-
this = c.getResolvedCrateOrigin() + "::_::" + c.getResolvedPath()
15-
)
9+
this.getParamList().getNumberOfParams() = 1 and
10+
this.getName().getText() = "clone"
1611
}
1712

1813
final override predicate propagatesFlow(

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

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,8 +1317,8 @@ private module Debug {
13171317
private Locatable getRelevantLocatable() {
13181318
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
13191319
result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
1320-
filepath.matches("%/illegal/main.rs") and
1321-
startline = 51
1320+
filepath.matches("%/main.rs") and
1321+
startline = 8
13221322
)
13231323
}
13241324

@@ -1327,6 +1327,14 @@ private module Debug {
13271327
result = resolvePath(path)
13281328
}
13291329

1330+
private ItemNode sdfsf(RelevantPath path, ImplItemNode impl, ItemNode frm) {
1331+
path = getRelevantLocatable() and
1332+
result = resolvePath(path) and
1333+
result = impl.resolveSelfTy() and
1334+
frm = impl.getASuccessorRec("from") and
1335+
frm instanceof AssocItemNode
1336+
}
1337+
13301338
predicate debugUseImportEdge(Use use, string name, ItemNode item) {
13311339
use = getRelevantLocatable() and
13321340
useImportEdge(use, name, item)
@@ -1347,3 +1355,59 @@ private module Debug {
13471355
fileImport(m, f)
13481356
}
13491357
}
1358+
1359+
private predicate sdfs(ImplItemNode impl) {
1360+
// resolvePath(impl.getSelfPath()).getLocation().getStartLine() = [35, 36]
1361+
impl.getLocation().getFile().getBaseName() = "main.rs" //and
1362+
// impl.getLocation().getStartLine() = [35 .. 38]
1363+
}
1364+
1365+
private import Type
1366+
private import TypeInference
1367+
1368+
private predicate sdf3(
1369+
AstNode n, Type t, ImplItemNode impl, string path, RelevantPath p, ImplOrTraitItemNode i,
1370+
TraitType tt, Function f, string name
1371+
) {
1372+
t = inferType(n) and
1373+
n.getLocation().getStartLine() = 29 and
1374+
t = TStruct(impl.resolveSelfTy()) and
1375+
// t = debugInferType(_, _) and
1376+
impl.toString() = "impl ...::Iterator for ...::Args { ... }" and
1377+
path = p.toStringDebug() and
1378+
p = impl.getTraitPath().getQualifier*() and
1379+
i = resolvePath(p) and
1380+
impl.isFullyParametric() and
1381+
tt = TTrait(i) and
1382+
f = tt.getMethod(name) and
1383+
f = i.getAnAssocItem() and
1384+
name = "collect" and
1385+
f = impl.resolveSelfTy().getASuccessor(name)
1386+
}
1387+
1388+
private predicate sdf4(
1389+
ImplItemNode impl, string path, RelevantPath p, ItemNode iter, Use u, string usePath,
1390+
RelevantPath usePathPrefix, ItemNode useResolved
1391+
) {
1392+
// t = debugInferType(_, _) and
1393+
impl.toString() = "impl ...::Iterator for ...::Args { ... }" and
1394+
path = p.toStringDebug() and
1395+
p = impl.getTraitPath().getQualifier*() and
1396+
iter = resolvePath(p) and
1397+
iter.getName() = "iter" and
1398+
u = iter.(Module).getItemList().getAnItem() and
1399+
usePath = u.getUseTree().getPath().toStringDebug() and
1400+
usePath = "self::traits::Iterator" and
1401+
usePathPrefix = u.getUseTree().getPath().getQualifier*() and
1402+
useResolved = resolvePath(usePathPrefix)
1403+
}
1404+
1405+
private predicate sdf5(ImplItemNode impl, string path, RelevantPath p, ItemNode iter, Module m) {
1406+
// t = debugInferType(_, _) and
1407+
impl.toString() = "impl ...::Iterator for ...::Args { ... }" and
1408+
path = p.toStringDebug() and
1409+
p = impl.getTraitPath().getQualifier*() and
1410+
iter = resolvePath(p) and
1411+
iter.getName() = "iter" and
1412+
m = iter.(Module).getItemList().getAnItem()
1413+
}

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

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,3 +1035,55 @@ import Cached
10351035
* Gets a type that `n` infers to, if any.
10361036
*/
10371037
Type inferType(AstNode n) { result = inferType(n, TypePath::nil()) }
1038+
1039+
/** Provides predicates for debugging the type inference implementation. */
1040+
private module Debug {
1041+
private Locatable getRelevantLocatable() {
1042+
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
1043+
result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
1044+
filepath.matches("%/main.rs") and
1045+
startline = [5 .. 10]
1046+
)
1047+
}
1048+
1049+
Type debugInferType(AstNode n, TypePath path) {
1050+
n = getRelevantLocatable() and
1051+
result = inferType(n, path)
1052+
}
1053+
1054+
private predicate sdf(Type t, ImplItemNode impl, TraitItemNode trait) {
1055+
t = debugInferType(_, _) and
1056+
t = TStruct(impl.resolveSelfTy()) and
1057+
trait = impl.resolveTraitTy()
1058+
}
1059+
1060+
private predicate sdf3(Type t, ImplItemNode impl) {
1061+
t = debugInferType(_, _) and
1062+
t = TStruct(impl.resolveSelfTy()) and
1063+
not impl.(Impl).hasTrait()
1064+
}
1065+
1066+
private predicate sdf2(Type t, ImplItemNode impl, string path) {
1067+
// t = debugInferType(_, _) and
1068+
impl.toString() = "impl ...::Iterator for ...::Args { ... }" and
1069+
t = TStruct(impl.resolveSelfTy()) and
1070+
path = impl.getTraitPath().toStringDebug()
1071+
}
1072+
1073+
Function debugResolveMethodCallExpr(MethodCallExpr mce) {
1074+
mce = getRelevantLocatable() and
1075+
result = resolveMethodCallExpr(mce)
1076+
}
1077+
1078+
private Function testdebugResolveMethodCallExpr(MethodCallExpr mce, Param self) {
1079+
mce = getRelevantLocatable() and
1080+
result = resolveMethodCallExpr(mce) and
1081+
self = result.getParamList().getAParam()
1082+
}
1083+
1084+
private Function testdebugResolveMethodCallExpr2(MethodCallExpr mce, SelfParam self) {
1085+
mce = getRelevantLocatable() and
1086+
result = resolveMethodCallExpr(mce) and
1087+
self = result.getParamList().getSelfParam()
1088+
}
1089+
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@
6060
| main.rs:238:17:238:25 | source(...) | main.rs:1:1:3:1 | fn source |
6161
| main.rs:239:9:239:15 | sink(...) | main.rs:5:1:7:1 | fn sink |
6262
| main.rs:242:5:242:17 | sink(...) | main.rs:5:1:7:1 | fn sink |
63-
| main.rs:246:13:246:55 | ...::block_on(...) | file://:0:0:0:0 | repo:https://github.com/rust-lang/futures-rs:futures-executor::_::crate::local_pool::block_on |
63+
| main.rs:246:13:246:55 | ...::block_on(...) | file://:0:0:0:0 | fn block_on |
6464
| main.rs:246:41:246:54 | async_source(...) | main.rs:227:1:231:1 | fn async_source |
6565
| main.rs:247:5:247:11 | sink(...) | main.rs:5:1:7:1 | fn sink |
66-
| main.rs:249:5:249:62 | ...::block_on(...) | file://:0:0:0:0 | repo:https://github.com/rust-lang/futures-rs:futures-executor::_::crate::local_pool::block_on |
66+
| main.rs:249:5:249:62 | ...::block_on(...) | file://:0:0:0:0 | fn block_on |
6767
| main.rs:249:33:249:61 | test_async_await_async_part(...) | main.rs:233:1:243:1 | fn test_async_await_async_part |
6868
| main.rs:253:5:253:22 | data_out_of_call(...) | main.rs:16:1:19:1 | fn data_out_of_call |
6969
| main.rs:254:5:254:35 | data_out_of_call_side_effect1(...) | main.rs:35:1:40:1 | fn data_out_of_call_side_effect1 |

0 commit comments

Comments
 (0)