Skip to content

Commit 0fbb0bf

Browse files
committed
Shared: Provenance-based filtering of flow summaries
1 parent 6c4a0bb commit 0fbb0bf

File tree

1 file changed

+81
-80
lines changed

1 file changed

+81
-80
lines changed

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

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

24+
/** Holds if `c` is defined in source code. */
25+
bindingset[c]
26+
predicate callableFromSource(SummarizedCallableBase c);
27+
2428
/**
2529
* A base class of elements that are candidates for flow source modeling.
2630
*/
@@ -268,6 +272,9 @@ module Make<
268272
this = verification and verification = "manual"
269273
}
270274

275+
/** Gets the verification part of this provenance. */
276+
string getVerification() { result = verification }
277+
271278
/**
272279
* Holds if this is a valid generated provenance value.
273280
*/
@@ -289,55 +296,36 @@ module Make<
289296
*
290297
* `preservesValue` indicates whether this is a value-preserving step or a taint-step.
291298
*
292-
* If `model` is non-empty then it indicates the provenance of the model
293-
* defining this flow.
299+
* `p` indicates the provenance of the flow.
300+
*
301+
* `isExact` indicates whether there exists a model for which this callable is an exact
302+
* match, that is, no overriding was used to identify this callable from the model.
303+
*
304+
* If `model` is non-empty then it indicates the origin of the model defining this flow.
294305
*/
295306
pragma[nomagic]
296307
abstract predicate propagatesFlow(
297-
string input, string output, boolean preservesValue, string model
308+
string input, string output, boolean preservesValue, Provenance p, boolean isExact,
309+
string model
298310
);
299311

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-
316312
/**
317313
* Holds if there exists a manual summary that applies to this callable.
318314
*/
319315
final predicate hasManualModel() {
320-
exists(Provenance p | p.isManual() and this.hasProvenance(p))
316+
any(Provenance p | this.propagatesFlow(_, _, _, p, _, _)).isManual()
321317
}
318+
}
322319

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" }
320+
final private class SummarizedCallableFinal = SummarizedCallable;
334321

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() }
322+
/**
323+
* A callable with a relevant flow summary.
324+
*
325+
* TODO: Write what is relevant.
326+
*/
327+
class RelevantSummarizedCallable extends SummarizedCallableFinal {
328+
RelevantSummarizedCallable() { this instanceof SummarizedCallableImpl }
341329
}
342330

343331
/** A source element. */
@@ -647,7 +635,7 @@ module Make<
647635
SummarizedCallableImpl callable, SummaryComponentStack input, SummaryComponentStack output,
648636
string whichOne
649637
) {
650-
callable.propagatesFlow(input, output, _, _) and
638+
callable.propagatesFlow(input, output, _, _, _, _) and
651639
(
652640
not isSupportedInputStack(input) and whichOne = "input"
653641
or
@@ -688,9 +676,9 @@ module Make<
688676

689677
private predicate summarySpec(string spec) {
690678
exists(SummarizedCallable c |
691-
c.propagatesFlow(spec, _, _, _)
679+
c.propagatesFlow(spec, _, _, _, _, _)
692680
or
693-
c.propagatesFlow(_, spec, _, _)
681+
c.propagatesFlow(_, spec, _, _, _, _)
694682
)
695683
or
696684
isRelevantSource(_, spec, _, _, _)
@@ -848,7 +836,7 @@ module Make<
848836
}
849837

850838
/**
851-
* A callable with a flow summary.
839+
* A callable with a relevant flow summary.
852840
*
853841
* This interface is not meant to be used directly, instead use the public
854842
* `SummarizedCallable` interface. However, _if_ you need to use this, make
@@ -857,13 +845,9 @@ module Make<
857845
*
858846
* ```ql
859847
* private class CAdapter extends SummarizedCallable instanceof C {
860-
* override predicate propagatesFlow(string input, string output, boolean preservesValue, string model) {
848+
* override predicate propagatesFlow(string input, string output, boolean preservesValue, Provenance p, string model) {
861849
* none()
862850
* }
863-
*
864-
* override predicate hasProvenance(Provenance provenance) {
865-
* C.super.hasProvenance(provenance)
866-
* }
867851
* }
868852
* ```
869853
*/
@@ -897,32 +881,26 @@ module Make<
897881
pragma[nomagic]
898882
abstract predicate propagatesFlow(
899883
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue,
900-
string model
884+
Provenance p, boolean isExact, string model
901885
);
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);
908886
}
909887

910888
pragma[nomagic]
911889
private predicate summary(
912890
SummarizedCallableImpl c, SummaryComponentStack input, SummaryComponentStack output,
913891
boolean preservesValue, string model
914892
) {
915-
c.propagatesFlow(input, output, preservesValue, model)
893+
c.propagatesFlow(input, output, preservesValue, _, _, model)
916894
or
917895
// observe side effects of callbacks on input arguments
918-
c.propagatesFlow(output, input, preservesValue, model) and
896+
c.propagatesFlow(output, input, preservesValue, _, _, model) and
919897
preservesValue = true and
920898
isCallbackParameter(input) and
921899
isContentOfArgument(output, _)
922900
or
923901
// flow from the receiver of a callback into the instance-parameter
924902
exists(SummaryComponentStack s, SummaryComponentStack callbackRef |
925-
c.propagatesFlow(s, _, _, model) or c.propagatesFlow(_, s, _, model)
903+
c.propagatesFlow(s, _, _, _, _, model) or c.propagatesFlow(_, s, _, _, _, model)
926904
|
927905
callbackRef = s.drop(_) and
928906
(isCallbackParameter(callbackRef) or callbackRef.head() = TReturnSummaryComponent(_)) and
@@ -948,8 +926,8 @@ module Make<
948926
SummaryComponentStack mid, boolean preservesValue1, boolean preservesValue2, string model1,
949927
string model2
950928
|
951-
c.propagatesFlow(input, mid, preservesValue1, model1) and
952-
c.propagatesFlow(mid, output, preservesValue2, model2) and
929+
c.propagatesFlow(input, mid, preservesValue1, _, _, model1) and
930+
c.propagatesFlow(mid, output, preservesValue2, _, _, model2) and
953931
mid.drop(mid.length() - 2) =
954932
SummaryComponentStack::push(TParameterSummaryComponent(_),
955933
SummaryComponentStack::singleton(TArgumentSummaryComponent(_))) and
@@ -2046,19 +2024,48 @@ module Make<
20462024
// adapter class for converting `SummarizedCallable`s to `SummarizedCallableImpl`s
20472025
private class SummarizedCallableImplAdapter extends SummarizedCallableImpl instanceof SummarizedCallable
20482026
{
2049-
override predicate propagatesFlow(
2050-
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue,
2051-
string model
2052-
) {
2027+
private SummaryComponentStack input_;
2028+
private SummaryComponentStack output_;
2029+
private boolean preservesValue_;
2030+
private Provenance p_;
2031+
private boolean isExact_;
2032+
private string model_;
2033+
2034+
SummarizedCallableImplAdapter() {
20532035
exists(AccessPath inSpec, AccessPath outSpec |
2054-
SummarizedCallable.super.propagatesFlow(inSpec, outSpec, preservesValue, model) and
2055-
interpretSpec(inSpec, input) and
2056-
interpretSpec(outSpec, output)
2036+
SummarizedCallable.super
2037+
.propagatesFlow(inSpec, outSpec, preservesValue_, p_, isExact_, model_) and
2038+
interpretSpec(inSpec, input_) and
2039+
interpretSpec(outSpec, output_)
2040+
|
2041+
if p_.isGenerated() or isExact_ = false
2042+
then
2043+
// Only apply generated models to functions in library code
2044+
not (p_.isGenerated() and callableFromSource(this)) and
2045+
// Only apply generated or inexact models to when no strictly better model exists
2046+
not exists(Provenance other |
2047+
SummarizedCallable.super.propagatesFlow(_, _, _, other, true, _)
2048+
or
2049+
neutralElement(this, "summary", other, true)
2050+
|
2051+
p_.isGenerated() and other.isManual()
2052+
or
2053+
p_.getVerification() = other.getVerification() and isExact_ = false
2054+
)
2055+
else any()
20572056
)
20582057
}
20592058

2060-
override predicate hasProvenance(Provenance provenance) {
2061-
SummarizedCallable.super.hasProvenance(provenance)
2059+
override predicate propagatesFlow(
2060+
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue,
2061+
Provenance p, boolean isExact, string model
2062+
) {
2063+
input = input_ and
2064+
output = output_ and
2065+
preservesValue = preservesValue_ and
2066+
p = p_ and
2067+
isExact = isExact_ and
2068+
model = model_
20622069
}
20632070
}
20642071

@@ -2492,26 +2499,20 @@ module Make<
24922499
string getCallableCsv();
24932500

24942501
predicate relevantSummary(
2495-
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
2502+
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue,
2503+
Provenance p
24962504
);
24972505
}
24982506

24992507
/** Provides a query predicate for outputting a set of relevant flow summaries. */
2500-
module TestSummaryOutput<RelevantSummarizedCallableSig RelevantSummarizedCallable> {
2508+
module TestSummaryOutput<RelevantSummarizedCallableSig RelSummarizedCallable> {
25012509
/** Render the kind in the format used in flow summaries. */
25022510
private string renderKind(boolean preservesValue) {
25032511
preservesValue = true and result = "value"
25042512
or
25052513
preservesValue = false and result = "taint"
25062514
}
25072515

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-
25152516
/**
25162517
* Holds if there exists a relevant summary callable with information roughly corresponding to `csv`.
25172518
* Used for testing.
@@ -2520,16 +2521,16 @@ module Make<
25202521
*/
25212522
query predicate summary(string csv) {
25222523
exists(
2523-
RelevantSummarizedCallable c, SummaryComponentStack input, SummaryComponentStack output,
2524-
boolean preservesValue
2524+
RelSummarizedCallable c, SummaryComponentStack input, SummaryComponentStack output,
2525+
boolean preservesValue, Provenance p
25252526
|
2526-
c.relevantSummary(input, output, preservesValue) and
2527+
c.relevantSummary(input, output, preservesValue, p) and
25272528
csv =
25282529
c.getCallableCsv() // Callable information
25292530
+ input.getMadRepresentation() + ";" // input
25302531
+ output.getMadRepresentation() + ";" // output
25312532
+ renderKind(preservesValue) + ";" // kind
2532-
+ renderProvenance(c) // provenance
2533+
+ p // provenance
25332534
)
25342535
}
25352536
}

0 commit comments

Comments
 (0)