Skip to content

Commit 37bc2bf

Browse files
committed
Shared: Deduplicate flow summaries.
1 parent 4d2f2b8 commit 37bc2bf

File tree

1 file changed

+52
-31
lines changed

1 file changed

+52
-31
lines changed

shared/mad/codeql/mad/modelgenerator/internal/ModelGeneratorImpl.qll

Lines changed: 52 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -345,12 +345,14 @@ module MakeModelGeneratorFactory<
345345
/**
346346
* Gets the summary model of `api`, if it follows the `fluent` programming pattern (returns `this`).
347347
*/
348-
private string captureQualifierFlow(DataFlowSummaryTargetApi api) {
348+
private string captureQualifierFlow(DataFlowSummaryTargetApi api, string input, string output) {
349349
exists(ReturnNodeExt ret |
350350
api = returnNodeEnclosingCallable(ret) and
351351
isOwnInstanceAccessNode(ret)
352352
) and
353-
result = ModelPrintingSummary::asLiftedValueModel(api, qualifierString(), "ReturnValue")
353+
input = qualifierString() and
354+
output = "ReturnValue" and
355+
result = ModelPrintingSummary::asLiftedValueModel(api, input, output)
354356
}
355357

356358
private int accessPathLimit0() { result = 2 }
@@ -430,7 +432,7 @@ module MakeModelGeneratorFactory<
430432
predicate isSink(DataFlow::Node sink) {
431433
sink instanceof ReturnNodeExt and
432434
not isOwnInstanceAccessNode(sink) and
433-
not exists(captureQualifierFlow(getAsExprEnclosingCallable(sink)))
435+
not exists(captureQualifierFlow(getAsExprEnclosingCallable(sink), _, _))
434436
}
435437

436438
predicate isAdditionalFlowStep = PropagateFlowConfigInput::isAdditionalFlowStep/4;
@@ -559,11 +561,24 @@ module MakeModelGeneratorFactory<
559561
*
560562
* `preservesValue` is `true` if the summary is value-preserving, and `false` otherwise.
561563
*/
562-
private string captureThroughFlow(DataFlowSummaryTargetApi api, boolean preservesValue) {
563-
exists(string input, string output |
564-
preservesValue = max(boolean b | captureThroughFlow0(api, _, input, _, output, b)) and
565-
result = ModelPrintingSummary::asLiftedModel(api, input, output, preservesValue)
566-
)
564+
private string captureThroughFlow(
565+
DataFlowSummaryTargetApi api, string input, string output, boolean preservesValue
566+
) {
567+
preservesValue = max(boolean b | captureThroughFlow0(api, _, input, _, output, b)) and
568+
result = ModelPrintingSummary::asLiftedModel(api, input, output, preservesValue)
569+
}
570+
571+
/**
572+
* Gets the summary model(s) of `api`, if there is flow `input` to
573+
* `output`. `preservesValue` is `true` if the summary is value-
574+
* preserving, and `false` otherwise.
575+
*/
576+
string captureFlow(
577+
DataFlowSummaryTargetApi api, string input, string output, boolean preservesValue
578+
) {
579+
result = captureQualifierFlow(api, input, output) and preservesValue = true
580+
or
581+
result = captureThroughFlow(api, input, output, preservesValue)
567582
}
568583

569584
/**
@@ -573,9 +588,7 @@ module MakeModelGeneratorFactory<
573588
* `preservesValue` is `true` if the summary is value-preserving, and `false` otherwise.
574589
*/
575590
string captureFlow(DataFlowSummaryTargetApi api, boolean preservesValue) {
576-
result = captureQualifierFlow(api) and preservesValue = true
577-
or
578-
result = captureThroughFlow(api, preservesValue)
591+
result = captureFlow(api, _, _, preservesValue)
579592
}
580593

581594
/**
@@ -947,19 +960,20 @@ module MakeModelGeneratorFactory<
947960
}
948961

949962
/**
950-
* Gets the content based summary model(s) of the API `api` (if there is flow from a parameter to
951-
* the return value or a parameter). `lift` is true, if the model should be lifted, otherwise false.
963+
* Gets the content based summary model(s) of the API `api` (if there is flow from `input` to
964+
* `output`). `lift` is true, if the model should be lifted, otherwise false.
952965
* `preservesValue` is `true` if the summary is value-preserving, and `false` otherwise.
953966
*
954967
* Models are lifted to the best type in case the read and store access paths do not
955968
* contain a field or synthetic field access.
956969
*/
957-
string captureFlow(ContentDataFlowSummaryTargetApi api, boolean lift, boolean preservesValue) {
958-
exists(string input, string output |
959-
captureFlow0(api, input, output, _, lift) and
960-
preservesValue = max(boolean p | captureFlow0(api, input, output, p, lift)) and
961-
result = ContentModelPrinting::asModel(api, input, output, preservesValue, lift)
962-
)
970+
string captureFlow(
971+
ContentDataFlowSummaryTargetApi api, string input, string output, boolean lift,
972+
boolean preservesValue
973+
) {
974+
captureFlow0(api, input, output, _, lift) and
975+
preservesValue = max(boolean p | captureFlow0(api, input, output, p, lift)) and
976+
result = ContentModelPrinting::asModel(api, input, output, preservesValue, lift)
963977
}
964978
}
965979

@@ -972,23 +986,30 @@ module MakeModelGeneratorFactory<
972986
* generate flow summaries using the heuristic based summary generator.
973987
*/
974988
string captureFlow(DataFlowSummaryTargetApi api, boolean lift) {
975-
exists(boolean preservesValue |
976-
result = ContentSensitive::captureFlow(api, lift, preservesValue)
977-
or
978-
not exists(DataFlowSummaryTargetApi api0 |
979-
// If the heuristic summary is value-preserving then we keep both
980-
// summaries. However, if we can generate any content-sensitive
981-
// summary (value-preserving or not) then we don't include any taint-
982-
// based heuristic summary.
983-
preservesValue = false
989+
result = ContentSensitive::captureFlow(api, _, _, lift, _)
990+
or
991+
exists(boolean preservesValue, string input, string output |
992+
not exists(
993+
DataFlowSummaryTargetApi api0, string input0, string output0, boolean preservesValue0
994+
|
995+
// If the heuristic summary is taint-based, and we can generate a content-sensitive
996+
// summary that is value-preserving then we omit generating any heuristic summary.
997+
preservesValue = false and
998+
preservesValue0 = true
999+
or
1000+
// However, if they're both value-preserving (or both taint-based) then we only
1001+
// generate a heuristic summary if we didn't generate a content-sensitive summary.
1002+
preservesValue = preservesValue0 and
1003+
input0 = input and
1004+
output0 = output
9841005
|
9851006
(api0 = api or api.lift() = api0) and
986-
exists(ContentSensitive::captureFlow(api0, false, _))
1007+
exists(ContentSensitive::captureFlow(api0, input0, output0, false, preservesValue0))
9871008
or
9881009
api0.lift() = api.lift() and
989-
exists(ContentSensitive::captureFlow(api0, true, _))
1010+
exists(ContentSensitive::captureFlow(api0, input0, output0, true, preservesValue0))
9901011
) and
991-
result = Heuristic::captureFlow(api, preservesValue) and
1012+
result = Heuristic::captureFlow(api, input, output, preservesValue) and
9921013
lift = true
9931014
)
9941015
}

0 commit comments

Comments
 (0)