Skip to content

Commit 3778964

Browse files
committed
Rust: Source/sink/barrier MaD trait models apply to implementations
1 parent c8783c1 commit 3778964

11 files changed

Lines changed: 351 additions & 274 deletions

File tree

cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,6 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
1717

1818
class SummarizedCallableBase = Function;
1919

20-
class SourceBase = Function;
21-
22-
class SinkBase = Function;
23-
2420
class FlowSummaryCallBase = CallInstruction;
2521

2622
predicate callableFromSource(SummarizedCallableBase c) { exists(c.getBlock()) }
@@ -232,7 +228,7 @@ private module Input2 implements Impl::Private::InputSig2 {
232228

233229
bindingset[source, sc]
234230
SourceSinkReportingElement getASourceReportingElement(
235-
Input::SourceBase source, Impl::Private::SummaryComponent sc
231+
Input::SummarizedCallableBase source, Impl::Private::SummaryComponent sc
236232
) {
237233
exists(Call call | call.getTarget() = source |
238234
sc = Impl::Private::SummaryComponent::return(_) and
@@ -312,7 +308,7 @@ private module Input2 implements Impl::Private::InputSig2 {
312308

313309
bindingset[sink, sc]
314310
SourceSinkReportingElement getASinkReportingElement(
315-
Input::SinkBase sink, Impl::Private::SummaryComponent sc
311+
Input::SummarizedCallableBase sink, Impl::Private::SummaryComponent sc
316312
) {
317313
exists(Call call, ArgumentPosition pos |
318314
call.getTarget() = sink and
@@ -525,9 +521,10 @@ private class SourceModelFunction extends Public::SourceElement instanceof Funct
525521
}
526522

527523
override predicate isSource(
528-
string output, string kind, Public::Provenance provenance, string model
524+
string output, string kind, Public::Provenance provenance, boolean isExact, string model
529525
) {
530-
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance, model)
526+
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance, model) and
527+
isExact = true
531528
}
532529
}
533530

@@ -544,7 +541,10 @@ private class SinkModelFunction extends Public::SinkElement instanceof Function
544541
this = interpretElement(namespace, type, subtypes, name, signature, ext)
545542
}
546543

547-
override predicate isSink(string input, string kind, Public::Provenance provenance, string model) {
548-
sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance, model)
544+
override predicate isSink(
545+
string input, string kind, Public::Provenance provenance, boolean isExact, string model
546+
) {
547+
sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance, model) and
548+
isExact = true
549549
}
550550
}

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ module FlowBarrier {
4444
Range() { any() }
4545

4646
override predicate isBarrier(
47-
string output, string kind, Impl::Public::Provenance provenance, string model
47+
string output, string kind, Impl::Public::Provenance provenance, boolean isExact, string model
4848
) {
49-
this.isBarrier(output, kind) and provenance = "manual" and model = ""
49+
this.isBarrier(output, kind) and provenance = "manual" and isExact = true and model = ""
5050
}
5151

5252
/**
@@ -67,9 +67,13 @@ module FlowBarrierGuard {
6767
Range() { any() }
6868

6969
override predicate isBarrierGuard(
70-
string input, string branch, string kind, Impl::Public::Provenance provenance, string model
70+
string input, string branch, string kind, Impl::Public::Provenance provenance,
71+
boolean isExact, string model
7172
) {
72-
this.isBarrierGuard(input, branch, kind) and provenance = "manual" and model = ""
73+
this.isBarrierGuard(input, branch, kind) and
74+
provenance = "manual" and
75+
isExact = true and
76+
model = ""
7377
}
7478

7579
/**

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ module FlowSink {
3636
Range() { any() }
3737

3838
override predicate isSink(
39-
string input, string kind, Impl::Public::Provenance provenance, string model
39+
string input, string kind, Impl::Public::Provenance provenance, boolean isExact, string model
4040
) {
41-
this.isSink(input, kind) and provenance = "manual" and model = ""
41+
this.isSink(input, kind) and provenance = "manual" and isExact = true and model = ""
4242
}
4343

4444
/**

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ module FlowSource {
4242
Range() { any() }
4343

4444
override predicate isSource(
45-
string output, string kind, Impl::Public::Provenance provenance, string model
45+
string output, string kind, Impl::Public::Provenance provenance, boolean isExact, string model
4646
) {
47-
this.isSource(output, kind) and provenance = "manual" and model = ""
47+
this.isSource(output, kind) and provenance = "manual" and isExact = true and model = ""
4848
}
4949

5050
/**

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

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,12 @@ module Input implements InputSig<Location, RustDataFlow> {
4343
result.asSummarizedCallable() = c
4444
}
4545

46-
class SourceBase = Function;
47-
48-
class SinkBase = Function;
49-
5046
predicate neutralElement(
5147
Input::SummarizedCallableBase c, string kind, string provenance, boolean isExact
5248
) {
53-
exists(string path |
54-
neutralModel(path, kind, provenance, _) and
55-
c.getCanonicalPath() = path and
56-
isExact = true
49+
exists(string path, Provenance orig |
50+
neutralModel(path, kind, orig, _) and
51+
interpretPath(path, c, orig, provenance, isExact)
5752
)
5853
}
5954

@@ -170,7 +165,7 @@ module Input2 implements Impl::Private::InputSig2 {
170165
}
171166

172167
SourceSinkReportingElement getASourceReportingElement(
173-
Input::SourceBase source, Impl::Private::SummaryComponent sc
168+
Input::SummarizedCallableBase source, Impl::Private::SummaryComponent sc
174169
) {
175170
exists(Call call | call.getResolvedTarget() = source |
176171
sc = Impl::Private::SummaryComponent::return(_) and
@@ -200,7 +195,7 @@ module Input2 implements Impl::Private::InputSig2 {
200195
}
201196

202197
SourceSinkReportingElement getASinkReportingElement(
203-
Input::SinkBase sink, Impl::Private::SummaryComponent sc
198+
Input::SummarizedCallableBase sink, Impl::Private::SummaryComponent sc
204199
) {
205200
exists(Call call |
206201
call.getResolvedTarget() = sink and

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

Lines changed: 65 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,22 @@ predicate interpretModelForTest(QlBuiltins::ExtensionId madId, string model) {
174174
)
175175
}
176176

177+
bindingset[path, orig]
178+
pragma[inline_late]
179+
predicate interpretPath(string path, Function f, Provenance orig, Provenance p, boolean isExact) {
180+
exists(Function f0 | f0.getCanonicalPath() = path |
181+
f = f0 and
182+
isExact = true and
183+
p = orig
184+
or
185+
f.implements(f0) and
186+
isExact = false and
187+
// making inherited models generated means that source code definitions and
188+
// exact generated models take precedence
189+
p = "hq-generated"
190+
)
191+
}
192+
177193
private class SummarizedCallableFromModel extends SummarizedCallable::Range {
178194
string input_;
179195
string output_;
@@ -183,19 +199,9 @@ private class SummarizedCallableFromModel extends SummarizedCallable::Range {
183199
QlBuiltins::ExtensionId madId;
184200

185201
SummarizedCallableFromModel() {
186-
exists(string path, Function f, Provenance p |
202+
exists(string path, Provenance p |
187203
summaryModel(path, input_, output_, kind, p, madId) and
188-
f.getCanonicalPath() = path
189-
|
190-
this = f and
191-
isExact_ = true and
192-
p_ = p
193-
or
194-
this.implements(f) and
195-
isExact_ = false and
196-
// making inherited models generated means that source code definitions and
197-
// exact generated models take precedence
198-
p_ = "hq-generated"
204+
interpretPath(path, this, p, p_, isExact_)
199205
)
200206
}
201207

@@ -246,78 +252,93 @@ private class SummarizedCallableWithCallback extends SummarizedCallable::Range {
246252

247253
private class FlowSourceFromModel extends FlowSource::Range {
248254
private string path;
255+
private Provenance orig;
256+
private Provenance p_;
257+
private boolean isExact_;
249258

250259
FlowSourceFromModel() {
251-
sourceModel(path, _, _, _, _) and
252-
this.getCanonicalPath() = path
260+
sourceModel(path, _, _, orig, _) and
261+
interpretPath(path, this, orig, p_, isExact_)
253262
}
254263

255-
override predicate isSource(string output, string kind, Provenance provenance, string model) {
264+
override predicate isSource(
265+
string output, string kind, Provenance provenance, boolean isExact, string model
266+
) {
256267
exists(QlBuiltins::ExtensionId madId |
257-
sourceModel(path, output, kind, provenance, madId) and
258-
model = "MaD:" + madId.toString()
259-
) and
260-
// Only apply generated models when no neutral model exists
261-
// (the shared code only applies neutral models to summaries at present)
262-
not (
263-
provenance.isGenerated() and
264-
neutralModel(path, "source", _, _)
268+
sourceModel(path, output, kind, orig, madId) and
269+
model = "MaD:" + madId.toString() and
270+
provenance = p_ and
271+
isExact = isExact_
265272
)
266273
}
267274
}
268275

269276
private class FlowSinkFromModel extends FlowSink::Range {
270277
private string path;
278+
private Provenance orig;
279+
private Provenance p_;
280+
private boolean isExact_;
271281

272282
FlowSinkFromModel() {
273-
sinkModel(path, _, _, _, _) and
274-
this.getCanonicalPath() = path
283+
sinkModel(path, _, _, orig, _) and
284+
interpretPath(path, this, orig, p_, isExact_)
275285
}
276286

277-
override predicate isSink(string input, string kind, Provenance provenance, string model) {
287+
override predicate isSink(
288+
string input, string kind, Provenance provenance, boolean isExact, string model
289+
) {
278290
exists(QlBuiltins::ExtensionId madId |
279-
sinkModel(path, input, kind, provenance, madId) and
280-
model = "MaD:" + madId.toString()
281-
) and
282-
// Only apply generated models when no neutral model exists
283-
// (the shared code only applies neutral models to summaries at present)
284-
not (
285-
provenance.isGenerated() and
286-
neutralModel(path, "sink", _, _)
291+
sinkModel(path, input, kind, orig, madId) and
292+
model = "MaD:" + madId.toString() and
293+
provenance = p_ and
294+
isExact = isExact_
287295
)
288296
}
289297
}
290298

291299
private class FlowBarrierFromModel extends FlowBarrier::Range {
292300
private string path;
301+
private Provenance orig;
302+
private Provenance p_;
303+
private boolean isExact_;
293304

294305
FlowBarrierFromModel() {
295-
barrierModel(path, _, _, _, _) and
296-
this.getCanonicalPath() = path
306+
barrierModel(path, _, _, orig, _) and
307+
interpretPath(path, this, orig, p_, isExact_)
297308
}
298309

299-
override predicate isBarrier(string output, string kind, Provenance provenance, string model) {
310+
override predicate isBarrier(
311+
string output, string kind, Provenance provenance, boolean isExact, string model
312+
) {
300313
exists(QlBuiltins::ExtensionId madId |
301-
barrierModel(path, output, kind, provenance, madId) and
302-
model = "MaD:" + madId.toString()
314+
barrierModel(path, output, kind, _, madId) and
315+
model = "MaD:" + madId.toString() and
316+
provenance = p_ and
317+
isExact = isExact_
303318
)
304319
}
305320
}
306321

307322
private class FlowBarrierGuardFromModel extends FlowBarrierGuard::Range {
308323
private string path;
324+
private Provenance orig;
325+
private Provenance p_;
326+
private boolean isExact_;
309327

310328
FlowBarrierGuardFromModel() {
311-
barrierGuardModel(path, _, _, _, _, _) and
312-
this.getCanonicalPath() = path
329+
barrierGuardModel(path, _, _, _, orig, _) and
330+
interpretPath(path, this, orig, p_, isExact_)
313331
}
314332

315333
override predicate isBarrierGuard(
316-
string input, string acceptingValue, string kind, Provenance provenance, string model
334+
string input, string acceptingValue, string kind, Provenance provenance, boolean isExact,
335+
string model
317336
) {
318337
exists(QlBuiltins::ExtensionId madId |
319-
barrierGuardModel(path, input, acceptingValue, kind, provenance, madId) and
320-
model = "MaD:" + madId.toString()
338+
barrierGuardModel(path, input, acceptingValue, kind, _, madId) and
339+
model = "MaD:" + madId.toString() and
340+
provenance = p_ and
341+
isExact = isExact_
321342
)
322343
}
323344
}

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ edges
44
| main.rs:21:13:21:21 | source(...) | main.rs:21:9:21:9 | s | provenance | |
55
| main.rs:32:9:32:9 | s | main.rs:33:10:33:10 | s | provenance | |
66
| main.rs:32:13:32:21 | source(...) | main.rs:32:9:32:9 | s | provenance | |
7-
| main.rs:63:9:63:9 | s | main.rs:65:10:65:10 | s | provenance | |
8-
| main.rs:63:13:63:21 | source(...) | main.rs:63:9:63:9 | s | provenance | |
97
nodes
108
| main.rs:17:10:17:18 | source(...) | semmle.label | source(...) |
119
| main.rs:21:9:21:9 | s | semmle.label | s |
@@ -14,13 +12,9 @@ nodes
1412
| main.rs:32:9:32:9 | s | semmle.label | s |
1513
| main.rs:32:13:32:21 | source(...) | semmle.label | source(...) |
1614
| main.rs:33:10:33:10 | s | semmle.label | s |
17-
| main.rs:63:9:63:9 | s | semmle.label | s |
18-
| main.rs:63:13:63:21 | source(...) | semmle.label | source(...) |
19-
| main.rs:65:10:65:10 | s | semmle.label | s |
2015
subpaths
2116
testFailures
2217
#select
2318
| main.rs:17:10:17:18 | source(...) | main.rs:17:10:17:18 | source(...) | main.rs:17:10:17:18 | source(...) | $@ | main.rs:17:10:17:18 | source(...) | source(...) |
2419
| main.rs:22:10:22:10 | s | main.rs:21:13:21:21 | source(...) | main.rs:22:10:22:10 | s | $@ | main.rs:21:13:21:21 | source(...) | source(...) |
2520
| main.rs:33:10:33:10 | s | main.rs:32:13:32:21 | source(...) | main.rs:33:10:33:10 | s | $@ | main.rs:32:13:32:21 | source(...) | source(...) |
26-
| main.rs:65:10:65:10 | s | main.rs:63:13:63:21 | source(...) | main.rs:65:10:65:10 | s | $@ | main.rs:63:13:63:21 | source(...) | source(...) |

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ impl<T> MyBarrierTrait3 for T {
6262
fn with_trait_barriers() {
6363
let s = source(2);
6464
<()>::sanitize2(s);
65-
sink(s); // $ SPURIOUS: hasValueFlow=2
65+
sink(s);
6666
<()>::sanitize3(s);
6767
sink(s);
6868
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -527,12 +527,12 @@ fn test_trait_model<T: Ord>(x: T) {
527527
sink(x9); // $ hasValueFlow=30
528528

529529
let x10 = <()>::produce2(31);
530-
sink(x10); // $ MISSING: hasValueFlow=31
530+
sink(x10); // $ hasValueFlow=31
531531

532532
let x11 = <()>::produce3(32);
533533
sink(x11); // $ hasValueFlow=32
534534

535-
<()>::consume2(source(33)); // $ MISSING: hasValueFlow=33
535+
<()>::consume2(source(33)); // $ hasValueFlow=33
536536

537537
<()>::consume3(source(34)); // $ hasValueFlow=34
538538
}

0 commit comments

Comments
 (0)