@@ -11,6 +11,7 @@ private import codeql.dataflow.internal.ContentDataFlowImpl
1111private import codeql.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon
1212private import codeql.util.Location
1313private import ModelPrinting
14+ private import codeql.util.Unit
1415
1516/**
1617 * Provides language-specific model generator parameters.
@@ -464,14 +465,22 @@ module MakeModelGenerator<
464465 override string toString ( ) { result = "TaintStore(" + step + ")" }
465466 }
466467
467- /**
468- * A data flow configuration for tracking flow through APIs.
469- * The sources are the parameters of an API and the sinks are the return values (excluding `this`) and parameters.
470- *
471- * This can be used to generate Flow summaries for APIs from parameter to return.
472- */
473- private module PropagateFlowConfig implements DataFlow:: StateConfigSig {
474- class FlowState = TaintState ;
468+ private signature module PropagateFlowConfigInputSig {
469+ class FlowState ;
470+
471+ FlowState initialState ( ) ;
472+
473+ default predicate isAdditionalFlowStep (
474+ DataFlow:: Node node1 , FlowState state1 , DataFlow:: Node node2 , FlowState state2
475+ ) {
476+ none ( )
477+ }
478+ }
479+
480+ private module PropagateFlowConfig< PropagateFlowConfigInputSig PropagateFlowConfigInput>
481+ implements DataFlow:: StateConfigSig
482+ {
483+ import PropagateFlowConfigInput
475484
476485 predicate isSource ( DataFlow:: Node source , FlowState state ) {
477486 source instanceof DataFlow:: ParameterNode and
@@ -480,7 +489,7 @@ module MakeModelGenerator<
480489 c instanceof DataFlowSummaryTargetApi and
481490 not isUninterestingForHeuristicDataFlowModels ( c )
482491 ) and
483- state . ( TaintRead ) . getStep ( ) = 0
492+ state = initialState ( )
484493 }
485494
486495 predicate isSink ( DataFlow:: Node sink , FlowState state ) {
@@ -494,6 +503,31 @@ module MakeModelGenerator<
494503 not exists ( captureQualifierFlow ( getAsExprEnclosingCallable ( sink ) ) )
495504 }
496505
506+ predicate isAdditionalFlowStep = PropagateFlowConfigInput:: isAdditionalFlowStep / 4 ;
507+
508+ predicate isBarrier ( DataFlow:: Node n ) {
509+ exists ( Type t | t = n .( NodeExtended ) .getType ( ) and not isRelevantType ( t ) )
510+ }
511+
512+ DataFlow:: FlowFeature getAFeature ( ) {
513+ result instanceof DataFlow:: FeatureEqualSourceSinkCallContext
514+ }
515+ }
516+
517+ /**
518+ * A module used to construct a data flow configuration for tracking taint-
519+ * flow through APIs.
520+ * The sources are the parameters of an API and the sinks are the return
521+ * values (excluding `this`) and parameters.
522+ *
523+ * This can be used to generate flow summaries for APIs from parameter to
524+ * return.
525+ */
526+ module PropagateFlowConfigInputTaintInput implements PropagateFlowConfigInputSig {
527+ class FlowState = TaintState ;
528+
529+ FlowState initialState ( ) { result .( TaintRead ) .getStep ( ) = 0 }
530+
497531 predicate isAdditionalFlowStep (
498532 DataFlow:: Node node1 , FlowState state1 , DataFlow:: Node node2 , FlowState state2
499533 ) {
@@ -515,51 +549,94 @@ module MakeModelGenerator<
515549 state1 .( TaintRead ) .getStep ( ) + 1 = state2 .( TaintRead ) .getStep ( )
516550 )
517551 }
552+ }
518553
519- predicate isBarrier ( DataFlow:: Node n ) {
520- exists ( Type t | t = n .( NodeExtended ) .getType ( ) and not isRelevantType ( t ) )
521- }
554+ /**
555+ * A data flow configuration for tracking taint-flow through APIs.
556+ * The sources are the parameters of an API and the sinks are the return
557+ * values (excluding `this`) and parameters.
558+ *
559+ * This can be used to generate flow summaries for APIs from parameter to
560+ * return.
561+ */
562+ private module PropagateTaintFlowConfig =
563+ PropagateFlowConfig< PropagateFlowConfigInputTaintInput > ;
522564
523- DataFlow:: FlowFeature getAFeature ( ) {
524- result instanceof DataFlow:: FeatureEqualSourceSinkCallContext
525- }
565+ module PropagateTaintFlow = TaintTracking:: GlobalWithState< PropagateTaintFlowConfig > ;
566+
567+ /**
568+ * A module used to construct a data flow configuration for tracking
569+ * data flow through APIs.
570+ * The sources are the parameters of an API and the sinks are the return
571+ * values (excluding `this`) and parameters.
572+ *
573+ * This can be used to generate value-preserving flow summaries for APIs
574+ * from parameter to return.
575+ */
576+ module PropagateFlowConfigInputDataFlowInput implements PropagateFlowConfigInputSig {
577+ class FlowState = Unit ;
578+
579+ FlowState initialState ( ) { any ( ) }
526580 }
527581
528- module PropagateFlow = TaintTracking:: GlobalWithState< PropagateFlowConfig > ;
582+ /**
583+ * A data flow configuration for tracking data flow through APIs.
584+ * The sources are the parameters of an API and the sinks are the return
585+ * values (excluding `this`) and parameters.
586+ *
587+ * This can be used to generate flow summaries for APIs from parameter to
588+ * return.
589+ */
590+ private module PropagateDataFlowConfig =
591+ PropagateFlowConfig< PropagateFlowConfigInputDataFlowInput > ;
592+
593+ module PropagateDataFlow = DataFlow:: GlobalWithState< PropagateDataFlowConfig > ;
529594
530595 /**
531596 * Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter.
532597 */
598+ bindingset [ preservesValue]
533599 string captureThroughFlow0 (
534- DataFlowSummaryTargetApi api , DataFlow:: ParameterNode p , ReturnNodeExt returnNodeExt
600+ DataFlowSummaryTargetApi api , DataFlow:: ParameterNode p , ReturnNodeExt returnNodeExt ,
601+ boolean preservesValue
535602 ) {
536603 exists ( string input , string output |
537604 getEnclosingCallable ( p ) = api and
538605 getEnclosingCallable ( returnNodeExt ) = api and
539606 input = parameterNodeAsInput ( p ) and
540607 output = getOutput ( returnNodeExt ) and
541608 input != output and
542- result = ModelPrinting:: asLiftedTaintModel ( api , input , output )
609+ result = ModelPrinting:: asLiftedTaintModel ( api , input , output , preservesValue )
543610 )
544611 }
545612
546613 /**
547614 * Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter.
615+ *
616+ * `preservesValue` is `true` if the summary is value-preserving, and `false` otherwise.
548617 */
549- private string captureThroughFlow ( DataFlowSummaryTargetApi api ) {
618+ private string captureThroughFlow ( DataFlowSummaryTargetApi api , boolean preservesValue ) {
550619 exists ( DataFlow:: ParameterNode p , ReturnNodeExt returnNodeExt |
551- PropagateFlow:: flow ( p , returnNodeExt ) and
552- result = captureThroughFlow0 ( api , p , returnNodeExt )
620+ PropagateDataFlow:: flow ( p , returnNodeExt ) and preservesValue = true
621+ or
622+ not PropagateDataFlow:: flow ( p , returnNodeExt ) and
623+ PropagateTaintFlow:: flow ( p , returnNodeExt ) and
624+ preservesValue = false
625+ |
626+ result = captureThroughFlow0 ( api , p , returnNodeExt , preservesValue )
553627 )
554628 }
555629
556630 /**
557631 * Gets the summary model(s) of `api`, if there is flow from parameters to the
558632 * return value or parameter or if `api` is a fluent API.
633+ *
634+ * `preservesValue` is `true` if the summary is value-preserving, and `false` otherwise.
559635 */
560- string captureFlow ( DataFlowSummaryTargetApi api ) {
561- result = captureQualifierFlow ( api ) or
562- result = captureThroughFlow ( api )
636+ string captureHeuristicFlow ( DataFlowSummaryTargetApi api , boolean preservesValue ) {
637+ result = captureQualifierFlow ( api ) and preservesValue = true
638+ or
639+ result = captureThroughFlow ( api , preservesValue )
563640 }
564641
565642 /**
@@ -569,7 +646,7 @@ module MakeModelGenerator<
569646 */
570647 string captureNoFlow ( DataFlowSummaryTargetApi api ) {
571648 not exists ( DataFlowSummaryTargetApi api0 |
572- exists ( captureFlow ( api0 ) ) and api0 .lift ( ) = api .lift ( )
649+ exists ( captureFlow ( api0 , _ ) ) and api0 .lift ( ) = api .lift ( )
573650 ) and
574651 api .isRelevant ( ) and
575652 result = ModelPrinting:: asNeutralSummaryModel ( api )
@@ -1024,12 +1101,13 @@ module MakeModelGenerator<
10241101 /**
10251102 * Gets the content based summary model(s) of the API `api` (if there is flow from a parameter to
10261103 * the return value or a parameter). `lift` is true, if the model should be lifted, otherwise false.
1104+ * `preservesValue` is `true` if the summary is value-preserving, and `false` otherwise.
10271105 *
10281106 * Models are lifted to the best type in case the read and store access paths do not
10291107 * contain a field or synthetic field access.
10301108 */
1031- string captureFlow ( ContentDataFlowSummaryTargetApi api , boolean lift ) {
1032- exists ( string input , string output , boolean preservesValue |
1109+ string captureFlow ( ContentDataFlowSummaryTargetApi api , boolean lift , boolean preservesValue ) {
1110+ exists ( string input , string output |
10331111 captureFlow0 ( api , input , output , _, lift ) and
10341112 preservesValue = max ( boolean p | captureFlow0 ( api , input , output , p , lift ) ) and
10351113 result = ContentModelPrinting:: asModel ( api , input , output , preservesValue , lift )
@@ -1046,17 +1124,19 @@ module MakeModelGenerator<
10461124 * generate flow summaries using the heuristic based summary generator.
10471125 */
10481126 string captureFlow ( DataFlowSummaryTargetApi api , boolean lift ) {
1049- result = ContentSensitive:: captureFlow ( api , lift )
1050- or
1051- not exists ( DataFlowSummaryTargetApi api0 |
1052- ( api0 = api or api .lift ( ) = api0 ) and
1053- exists ( ContentSensitive:: captureFlow ( api0 , false ) )
1127+ exists ( boolean preservesValue |
1128+ result = ContentSensitive:: captureFlow ( api , lift , preservesValue )
10541129 or
1055- api0 .lift ( ) = api .lift ( ) and
1056- exists ( ContentSensitive:: captureFlow ( api0 , true ) )
1057- ) and
1058- result = Heuristic:: captureFlow ( api ) and
1059- lift = true
1130+ not exists ( DataFlowSummaryTargetApi api0 |
1131+ ( api0 = api or api .lift ( ) = api0 ) and
1132+ exists ( ContentSensitive:: captureFlow ( api0 , false , preservesValue ) )
1133+ or
1134+ api0 .lift ( ) = api .lift ( ) and
1135+ exists ( ContentSensitive:: captureFlow ( api0 , true , preservesValue ) )
1136+ ) and
1137+ result = Heuristic:: captureHeuristicFlow ( api , preservesValue ) and
1138+ lift = true
1139+ )
10601140 }
10611141
10621142 /**
0 commit comments