Skip to content

Commit cc254d9

Browse files
committed
C#: Adapt to changes in FlowSummaryImpl
1 parent 0fbb0bf commit cc254d9

File tree

14 files changed

+145
-5073
lines changed

14 files changed

+145
-5073
lines changed

csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ deprecated module SummaryComponentStack = Impl::Private::SummaryComponentStack;
1818

1919
deprecated class RequiredSummaryComponentStack = Impl::Private::RequiredSummaryComponentStack;
2020

21-
class SummarizedCallable = Impl::Public::SummarizedCallable;
21+
/** Provides the `Range` class used to define the extent of `SummarizedCallable`. */
22+
module SummarizedCallable {
23+
class Range = Impl::Public::SummarizedCallable;
24+
}
25+
26+
final class SummarizedCallable = Impl::Public::RelevantSummarizedCallable;
2227

2328
class Provenance = Impl::Public::Provenance;

csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -371,24 +371,9 @@ class NonDelegateDataFlowCall extends DataFlowCall, TNonDelegateCall {
371371
/** Gets the underlying call. */
372372
DispatchCall getDispatchCall() { result = dc }
373373

374-
pragma[nomagic]
375-
private predicate hasSourceTarget() { dc.getAStaticTarget().fromSource() }
376-
377374
pragma[nomagic]
378375
private FlowSummary::SummarizedCallable getASummarizedCallableTarget() {
379-
// Only use summarized callables with generated summaries in case
380-
// we are not able to dispatch to a source declaration.
381-
exists(boolean static |
382-
result = this.getATarget(static) and
383-
not (
384-
result.applyGeneratedModel() and
385-
this.hasSourceTarget()
386-
)
387-
|
388-
static = false
389-
or
390-
static = true and not result instanceof RuntimeCallable
391-
)
376+
result = this.getATarget(_)
392377
}
393378

394379
pragma[nomagic]

csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,7 @@ private predicate fieldOrPropertyStore(Expr e, ContentSet c, Expr src, Expr q, b
848848
FlowSummaryImpl::Private::SummarizedCallableImpl sc,
849849
FlowSummaryImpl::Private::SummaryComponentStack input, ContentSet readSet
850850
|
851-
sc.propagatesFlow(input, _, _, _) and
851+
sc.propagatesFlow(input, _, _, _, _, _) and
852852
input.contains(FlowSummaryImpl::Private::SummaryComponent::content(readSet)) and
853853
c.getAStoreContent() = readSet.getAReadContent()
854854
)
@@ -1021,7 +1021,6 @@ private class InstanceCallable extends Callable {
10211021
private Location l;
10221022

10231023
InstanceCallable() {
1024-
this = any(DataFlowCallable dfc).asCallable(l) and
10251024
not this.(Modifiable).isStatic() and
10261025
// local functions and delegate capture `this` and should therefore
10271026
// not have a `this` parameter
@@ -1119,6 +1118,7 @@ private module Cached {
11191118
p = c.asCallable(_).(CallableUsedInSource).getAParameter()
11201119
} or
11211120
TInstanceParameterNode(InstanceCallable c, Location l) {
1121+
c = any(DataFlowCallable dfc).asCallable(l) and
11221122
c instanceof CallableUsedInSource and
11231123
l = c.getARelevantLocation()
11241124
} or

csharp/ql/lib/semmle/code/csharp/dataflow/internal/ExternalFlow.qll

Lines changed: 26 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -380,20 +380,23 @@ private Declaration interpretExt(Declaration d, ExtPath ext) {
380380
/** Gets the source/sink/summary/neutral element corresponding to the supplied parameters. */
381381
pragma[nomagic]
382382
Declaration interpretElement(
383-
string namespace, string type, boolean subtypes, string name, string signature, string ext
383+
string namespace, string type, boolean subtypes, string name, string signature, string ext,
384+
boolean isExact
384385
) {
385386
elementSpec(namespace, type, subtypes, name, signature, ext) and
386387
exists(Declaration base, Declaration d |
387388
base = interpretBaseDeclaration(namespace, type, name, signature) and
388389
(
389-
d = base
390+
d = base and
391+
isExact = true
390392
or
391393
subtypes = true and
392394
(
393395
d.(UnboundCallable).overridesOrImplementsUnbound(base)
394396
or
395397
d = base.(UnboundValueOrRefType).getASubTypeUnbound+()
396-
)
398+
) and
399+
isExact = false
397400
)
398401
|
399402
result = interpretExt(d, ext)
@@ -586,71 +589,47 @@ string getSignature(UnboundCallable c) {
586589
}
587590

588591
private predicate interpretSummary(
589-
UnboundCallable c, string input, string output, string kind, string provenance, string model
592+
UnboundCallable c, string input, string output, string kind, string provenance, boolean isExact,
593+
string model
590594
) {
591595
exists(
592596
string namespace, string type, boolean subtypes, string name, string signature, string ext
593597
|
594598
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, provenance,
595599
model) and
596-
c = interpretElement(namespace, type, subtypes, name, signature, ext)
600+
c = interpretElement(namespace, type, subtypes, name, signature, ext, isExact)
597601
)
598602
}
599603

600-
predicate interpretNeutral(UnboundCallable c, string kind, string provenance) {
604+
predicate interpretNeutral(UnboundCallable c, string kind, string provenance, boolean isExact) {
601605
exists(string namespace, string type, string name, string signature |
602606
Extensions::neutralModel(namespace, type, name, signature, kind, provenance) and
603-
c = interpretElement(namespace, type, true, name, signature, "")
607+
c = interpretElement(namespace, type, true, name, signature, "", isExact)
604608
)
605609
}
606610

607611
// adapter class for converting Mad summaries to `SummarizedCallable`s
608612
private class SummarizedCallableAdapter extends SummarizedCallable {
609-
SummarizedCallableAdapter() {
610-
exists(Provenance provenance | interpretSummary(this, _, _, _, provenance, _) |
611-
not this.fromSource()
612-
or
613-
this.fromSource() and provenance.isManual()
614-
)
615-
}
616-
617-
private predicate relevantSummaryElementManual(
618-
string input, string output, string kind, string model
619-
) {
620-
exists(Provenance provenance |
621-
interpretSummary(this, input, output, kind, provenance, model) and
622-
provenance.isManual()
623-
)
624-
}
613+
string input_;
614+
string output_;
615+
string kind;
616+
Provenance p_;
617+
boolean isExact_;
618+
string model_;
625619

626-
private predicate relevantSummaryElementGenerated(
627-
string input, string output, string kind, string model
628-
) {
629-
exists(Provenance provenance |
630-
interpretSummary(this, input, output, kind, provenance, model) and
631-
provenance.isGenerated()
632-
) and
633-
not exists(Provenance provenance |
634-
interpretNeutral(this, "summary", provenance) and
635-
provenance.isManual()
636-
)
620+
SummarizedCallableAdapter() {
621+
interpretSummary(this, input_, output_, kind, p_, isExact_, model_)
637622
}
638623

639624
override predicate propagatesFlow(
640-
string input, string output, boolean preservesValue, string model
625+
string input, string output, boolean preservesValue, Provenance p, boolean isExact, string model
641626
) {
642-
exists(string kind |
643-
this.relevantSummaryElementManual(input, output, kind, model)
644-
or
645-
not this.relevantSummaryElementManual(_, _, _, _) and
646-
this.relevantSummaryElementGenerated(input, output, kind, model)
647-
|
648-
if kind = "value" then preservesValue = true else preservesValue = false
649-
)
650-
}
651-
652-
override predicate hasProvenance(Provenance provenance) {
653-
interpretSummary(this, _, _, _, provenance, _)
627+
input = input_ and
628+
output = output_ and
629+
(if kind = "value" then preservesValue = true else preservesValue = false) and
630+
p = p_ and
631+
isExact = isExact_ and
632+
model = model_
654633
}
655634
}
656635

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

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,24 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CsharpDataFlow>
1818

1919
class SummarizedCallableBase = UnboundCallable;
2020

21+
predicate callableFromSource(SummarizedCallableBase c) {
22+
c.fromSource() and
23+
not c.getFile().isStub() and
24+
not (
25+
c.getFile().extractedQlTest() and
26+
(
27+
c.getBody() instanceof ThrowElement or
28+
c.getBody().(BlockStmt).getStmt(0) instanceof ThrowElement
29+
)
30+
)
31+
}
32+
2133
class SourceBase = Void;
2234

2335
class SinkBase = Void;
2436

2537
predicate neutralElement(SummarizedCallableBase c, string kind, string provenance, boolean isExact) {
26-
interpretNeutral(c, kind, provenance) and
27-
// isExact is not needed for C#.
28-
isExact = false
38+
interpretNeutral(c, kind, provenance, isExact)
2939
}
3040

3141
ArgumentPosition callbackSelfParameterPosition() { result.isDelegateSelf() }
@@ -216,7 +226,7 @@ module SourceSinkInterpretationInput implements
216226
string namespace, string type, boolean subtypes, string name, string signature, string ext
217227
|
218228
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance, model) and
219-
e = interpretElement(namespace, type, subtypes, name, signature, ext)
229+
e = interpretElement(namespace, type, subtypes, name, signature, ext, _)
220230
)
221231
}
222232

@@ -227,7 +237,7 @@ module SourceSinkInterpretationInput implements
227237
string namespace, string type, boolean subtypes, string name, string signature, string ext
228238
|
229239
sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance, model) and
230-
e = interpretElement(namespace, type, subtypes, name, signature, ext)
240+
e = interpretElement(namespace, type, subtypes, name, signature, ext, _)
231241
)
232242
}
233243

@@ -238,7 +248,7 @@ module SourceSinkInterpretationInput implements
238248
string namespace, string type, boolean subtypes, string name, string signature, string ext
239249
|
240250
barrierModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance, model) and
241-
e = interpretElement(namespace, type, subtypes, name, signature, ext)
251+
e = interpretElement(namespace, type, subtypes, name, signature, ext, _)
242252
)
243253
}
244254

@@ -251,7 +261,7 @@ module SourceSinkInterpretationInput implements
251261
|
252262
barrierGuardModel(namespace, type, subtypes, name, signature, ext, input, acceptingvalue,
253263
kind, provenance, model) and
254-
e = interpretElement(namespace, type, subtypes, name, signature, ext)
264+
e = interpretElement(namespace, type, subtypes, name, signature, ext, _)
255265
)
256266
}
257267

@@ -448,13 +458,14 @@ private class SummarizedCallableWithCallback extends Public::SummarizedCallable
448458
SummarizedCallableWithCallback() { mayInvokeCallback(this, pos) }
449459

450460
override predicate propagatesFlow(
451-
string input, string output, boolean preservesValue, string model
461+
string input, string output, boolean preservesValue, Public::Provenance provenance,
462+
boolean isExact, string model
452463
) {
453464
input = "Argument[" + pos + "]" and
454465
output = "Argument[" + pos + "].Parameter[delegate-self]" and
455466
preservesValue = true and
467+
provenance = "hq-generated" and
468+
isExact = true and
456469
model = "heuristic-callback"
457470
}
458-
459-
override predicate hasProvenance(Public::Provenance provenance) { provenance = "hq-generated" }
460471
}

csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -92,22 +92,17 @@ module EntityFramework {
9292
abstract class EFSummarizedCallable extends SummarizedCallableImpl {
9393
bindingset[this]
9494
EFSummarizedCallable() { any() }
95-
96-
override predicate hasProvenance(Provenance provenance) { provenance = "manual" }
9795
}
9896

9997
// see `SummarizedCallableImpl` qldoc
10098
private class EFSummarizedCallableAdapter extends SummarizedCallable instanceof EFSummarizedCallable
10199
{
102100
override predicate propagatesFlow(
103-
string input, string output, boolean preservesValue, string model
101+
string input, string output, boolean preservesValue, Provenance provenance, boolean isExact,
102+
string model
104103
) {
105104
none()
106105
}
107-
108-
override predicate hasProvenance(Provenance provenance) {
109-
EFSummarizedCallable.super.hasProvenance(provenance)
110-
}
111106
}
112107

113108
/** The class ``Microsoft.EntityFrameworkCore.DbQuery`1`` or ``System.Data.Entity.DbQuery`1``. */
@@ -177,11 +172,13 @@ module EntityFramework {
177172

178173
override predicate propagatesFlow(
179174
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue,
180-
string model
175+
Provenance p, boolean isExact, string model
181176
) {
182177
input = SummaryComponentStack::argument(0) and
183178
output = SummaryComponentStack::return() and
184179
preservesValue = false and
180+
p = "manual" and
181+
isExact = true and
185182
model = "RawSqlStringConstructorSummarizedCallable"
186183
}
187184
}
@@ -193,11 +190,13 @@ module EntityFramework {
193190

194191
override predicate propagatesFlow(
195192
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue,
196-
string model
193+
Provenance p, boolean isExact, string model
197194
) {
198195
input = SummaryComponentStack::argument(0) and
199196
output = SummaryComponentStack::return() and
200197
preservesValue = false and
198+
p = "manual" and
199+
isExact = true and
201200
model = "RawSqlStringConversionSummarizedCallable"
202201
}
203202
}
@@ -459,18 +458,20 @@ module EntityFramework {
459458
}
460459

461460
private class DbContextClassSetPropertySynthetic extends EFSummarizedCallable {
462-
private DbContextClassSetProperty p;
461+
private DbContextClassSetProperty prop;
463462

464-
DbContextClassSetPropertySynthetic() { this = p.getGetter() }
463+
DbContextClassSetPropertySynthetic() { this = prop.getGetter() }
465464

466465
override predicate propagatesFlow(
467466
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue,
468-
string model
467+
Provenance p, boolean isExact, string model
469468
) {
470469
exists(string name, DbContextClass c |
471470
preservesValue = true and
472-
name = c.getSyntheticName(output, _, p) and
471+
name = c.getSyntheticName(output, _, prop) and
473472
input = SummaryComponentStack::syntheticGlobal(name) and
473+
p = "manual" and
474+
isExact = true and
474475
model = "DbContextClassSetPropertySynthetic"
475476
)
476477
}
@@ -483,13 +484,15 @@ module EntityFramework {
483484

484485
override predicate propagatesFlow(
485486
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue,
486-
string model
487+
Provenance p, boolean isExact, string model
487488
) {
488489
exists(string name, Property mapped |
489490
preservesValue = true and
490491
c.input(input, mapped) and
491492
name = c.getSyntheticNameProj(mapped) and
492493
output = SummaryComponentStack::syntheticGlobal(name) and
494+
p = "manual" and
495+
isExact = true and
493496
model = "DbContextSaveChanges"
494497
)
495498
}

csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ module SummaryModelGeneratorInput implements SummaryModelGeneratorInputSig {
230230
}
231231

232232
private predicate hasManualSummaryModel(Callable api) {
233-
api = any(FlowSummaryImpl::Public::SummarizedCallable sc | sc.applyManualModel()) or
233+
api = any(FlowSummaryImpl::Public::SummarizedCallable sc | sc.hasManualModel()) or
234234
api = any(FlowSummaryImpl::Public::NeutralSummaryCallable sc | sc.hasManualModel())
235235
}
236236

csharp/ql/test/library-tests/dataflow/external-models/ExternalFlow.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,9 @@ void M4()
215215
Sink(Library.GeneratedFlowWithManualNeutral(o2)); // no flow because the modelled method has a manual neutral summary model
216216
}
217217

218-
object GeneratedFlow(object o) => throw null;
218+
object GeneratedFlow(object o) => null;
219219

220-
object GeneratedFlowArgs(object o1, object o2) => throw null;
220+
object GeneratedFlowArgs(object o1, object o2) => null;
221221

222222
static void Sink(object o) { }
223223
}

0 commit comments

Comments
 (0)