Skip to content

Commit 40464a1

Browse files
committed
Shared: Provenance-based filtering of flow summaries
1 parent 63329b4 commit 40464a1

File tree

1 file changed

+39
-82
lines changed

1 file changed

+39
-82
lines changed

shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 39 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ signature module InputSig<LocationSig Location, DF::InputSig<Location> Lang> {
2121
string toString();
2222
}
2323

24+
/** Holds if a generated summary is allowed for `c`. */
25+
default predicate allowGeneratedSummary(SummarizedCallableBase c) { any() }
26+
2427
/**
2528
* A base class of elements that are candidates for flow source modeling.
2629
*/
@@ -289,55 +292,18 @@ module Make<
289292
*
290293
* `preservesValue` indicates whether this is a value-preserving step or a taint-step.
291294
*
292-
* If `model` is non-empty then it indicates the provenance of the model
293-
* defining this flow.
295+
* `p` indicates the provenance of the flow.
296+
*
297+
* `isExact` indicates whether there exists a model for which this callable is an exact
298+
* match, that is, no overriding was used to identify this callable from the model.
299+
*
300+
* If `model` is non-empty then it indicates the origin of the model defining this flow.
294301
*/
295302
pragma[nomagic]
296303
abstract predicate propagatesFlow(
297-
string input, string output, boolean preservesValue, string model
304+
string input, string output, boolean preservesValue, Provenance p, boolean isExact,
305+
string model
298306
);
299-
300-
/**
301-
* Holds if there exists a generated summary that applies to this callable.
302-
*/
303-
final predicate hasGeneratedModel() {
304-
exists(Provenance p | p.isGenerated() and this.hasProvenance(p))
305-
}
306-
307-
/**
308-
* Holds if all the summaries that apply to this callable are auto generated and not manually created.
309-
* That is, only apply generated models, when there are no manual models.
310-
*/
311-
final predicate applyGeneratedModel() {
312-
this.hasGeneratedModel() and
313-
not this.hasManualModel()
314-
}
315-
316-
/**
317-
* Holds if there exists a manual summary that applies to this callable.
318-
*/
319-
final predicate hasManualModel() {
320-
exists(Provenance p | p.isManual() and this.hasProvenance(p))
321-
}
322-
323-
/**
324-
* Holds if there exists a manual summary that applies to this callable.
325-
* Always apply manual models if they exist.
326-
*/
327-
final predicate applyManualModel() { this.hasManualModel() }
328-
329-
/**
330-
* Holds if there exists a summary that applies to this callable
331-
* that has provenance `provenance`.
332-
*/
333-
predicate hasProvenance(Provenance provenance) { provenance = "manual" }
334-
335-
/**
336-
* Holds if there exists a model for which this callable is an exact
337-
* match, that is, no overriding was used to identify this callable from
338-
* the model.
339-
*/
340-
predicate hasExactModel() { none() }
341307
}
342308

343309
/** A source element. */
@@ -647,7 +613,7 @@ module Make<
647613
SummarizedCallableImpl callable, SummaryComponentStack input, SummaryComponentStack output,
648614
string whichOne
649615
) {
650-
callable.propagatesFlow(input, output, _, _) and
616+
callable.propagatesFlow(input, output, _, _, _, _) and
651617
(
652618
not isSupportedInputStack(input) and whichOne = "input"
653619
or
@@ -688,9 +654,9 @@ module Make<
688654

689655
private predicate summarySpec(string spec) {
690656
exists(SummarizedCallable c |
691-
c.propagatesFlow(spec, _, _, _)
657+
c.propagatesFlow(spec, _, _, _, _, _)
692658
or
693-
c.propagatesFlow(_, spec, _, _)
659+
c.propagatesFlow(_, spec, _, _, _, _)
694660
)
695661
or
696662
isRelevantSource(_, spec, _, _, _)
@@ -857,13 +823,9 @@ module Make<
857823
*
858824
* ```ql
859825
* private class CAdapter extends SummarizedCallable instanceof C {
860-
* override predicate propagatesFlow(string input, string output, boolean preservesValue, string model) {
826+
* override predicate propagatesFlow(string input, string output, boolean preservesValue, Provenance p, string model) {
861827
* none()
862828
* }
863-
*
864-
* override predicate hasProvenance(Provenance provenance) {
865-
* C.super.hasProvenance(provenance)
866-
* }
867829
* }
868830
* ```
869831
*/
@@ -897,32 +859,26 @@ module Make<
897859
pragma[nomagic]
898860
abstract predicate propagatesFlow(
899861
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue,
900-
string model
862+
Provenance p, boolean isExact, string model
901863
);
902-
903-
/**
904-
* Holds if there exists a summary that applies to this callable
905-
* that has provenance `provenance`.
906-
*/
907-
abstract predicate hasProvenance(Provenance provenance);
908864
}
909865

910866
pragma[nomagic]
911867
private predicate summary(
912868
SummarizedCallableImpl c, SummaryComponentStack input, SummaryComponentStack output,
913869
boolean preservesValue, string model
914870
) {
915-
c.propagatesFlow(input, output, preservesValue, model)
871+
c.propagatesFlow(input, output, preservesValue, _, _, model)
916872
or
917873
// observe side effects of callbacks on input arguments
918-
c.propagatesFlow(output, input, preservesValue, model) and
874+
c.propagatesFlow(output, input, preservesValue, _, _, model) and
919875
preservesValue = true and
920876
isCallbackParameter(input) and
921877
isContentOfArgument(output, _)
922878
or
923879
// flow from the receiver of a callback into the instance-parameter
924880
exists(SummaryComponentStack s, SummaryComponentStack callbackRef |
925-
c.propagatesFlow(s, _, _, model) or c.propagatesFlow(_, s, _, model)
881+
c.propagatesFlow(s, _, _, _, _, model) or c.propagatesFlow(_, s, _, _, _, model)
926882
|
927883
callbackRef = s.drop(_) and
928884
(isCallbackParameter(callbackRef) or callbackRef.head() = TReturnSummaryComponent(_)) and
@@ -948,8 +904,8 @@ module Make<
948904
SummaryComponentStack mid, boolean preservesValue1, boolean preservesValue2, string model1,
949905
string model2
950906
|
951-
c.propagatesFlow(input, mid, preservesValue1, model1) and
952-
c.propagatesFlow(mid, output, preservesValue2, model2) and
907+
c.propagatesFlow(input, mid, preservesValue1, _, _, model1) and
908+
c.propagatesFlow(mid, output, preservesValue2, _, _, model2) and
953909
mid.drop(mid.length() - 2) =
954910
SummaryComponentStack::push(TParameterSummaryComponent(_),
955911
SummaryComponentStack::singleton(TArgumentSummaryComponent(_))) and
@@ -2048,18 +2004,25 @@ module Make<
20482004
{
20492005
override predicate propagatesFlow(
20502006
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue,
2051-
string model
2007+
Provenance p, boolean isExact, string model
20522008
) {
20532009
exists(AccessPath inSpec, AccessPath outSpec |
2054-
SummarizedCallable.super.propagatesFlow(inSpec, outSpec, preservesValue, model) and
2010+
SummarizedCallable.super
2011+
.propagatesFlow(inSpec, outSpec, preservesValue, p, isExact, model) and
20552012
interpretSpec(inSpec, input) and
20562013
interpretSpec(outSpec, output)
2014+
|
2015+
p.isManual()
2016+
or
2017+
p.isGenerated() and
2018+
not exists(Provenance manual | manual.isManual() |
2019+
SummarizedCallable.super.propagatesFlow(_, _, _, manual, _, _)
2020+
or
2021+
neutralElement(this, "summary", manual, _)
2022+
) and
2023+
allowGeneratedSummary(this)
20572024
)
20582025
}
2059-
2060-
override predicate hasProvenance(Provenance provenance) {
2061-
SummarizedCallable.super.hasProvenance(provenance)
2062-
}
20632026
}
20642027

20652028
/** Holds if component `c` of specification `spec` cannot be parsed. */
@@ -2492,7 +2455,8 @@ module Make<
24922455
string getCallableCsv();
24932456

24942457
predicate relevantSummary(
2495-
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
2458+
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue,
2459+
Provenance p
24962460
);
24972461
}
24982462

@@ -2505,13 +2469,6 @@ module Make<
25052469
preservesValue = false and result = "taint"
25062470
}
25072471

2508-
private string renderProvenance(SummarizedCallable c) {
2509-
exists(Provenance p | p.isManual() and c.hasProvenance(p) and result = p.toString())
2510-
or
2511-
not c.applyManualModel() and
2512-
c.hasProvenance(result)
2513-
}
2514-
25152472
/**
25162473
* Holds if there exists a relevant summary callable with information roughly corresponding to `csv`.
25172474
* Used for testing.
@@ -2521,15 +2478,15 @@ module Make<
25212478
query predicate summary(string csv) {
25222479
exists(
25232480
RelevantSummarizedCallable c, SummaryComponentStack input, SummaryComponentStack output,
2524-
boolean preservesValue
2481+
boolean preservesValue, Provenance p
25252482
|
2526-
c.relevantSummary(input, output, preservesValue) and
2483+
c.relevantSummary(input, output, preservesValue, p) and
25272484
csv =
25282485
c.getCallableCsv() // Callable information
25292486
+ input.getMadRepresentation() + ";" // input
25302487
+ output.getMadRepresentation() + ";" // output
25312488
+ renderKind(preservesValue) + ";" // kind
2532-
+ renderProvenance(c) // provenance
2489+
+ p // provenance
25332490
)
25342491
}
25352492
}

0 commit comments

Comments
 (0)