@@ -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,53 +549,102 @@ 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 captureFlow ( DataFlowSummaryTargetApi api , boolean preservesValue ) {
637+ result = captureQualifierFlow ( api ) and preservesValue = true
638+ or
639+ result = captureThroughFlow ( api , preservesValue )
563640 }
564641
642+ /**
643+ * Gets the summary model(s) of `api`, if there is flow from parameters to the
644+ * return value or parameter or if `api` is a fluent API.
645+ */
646+ string captureFlow ( DataFlowSummaryTargetApi api ) { result = captureFlow ( api , _) }
647+
565648 /**
566649 * Gets the neutral summary model for `api`, if any.
567650 * A neutral summary model is generated, if we are not generating
@@ -1024,17 +1107,29 @@ module MakeModelGenerator<
10241107 /**
10251108 * Gets the content based summary model(s) of the API `api` (if there is flow from a parameter to
10261109 * the return value or a parameter). `lift` is true, if the model should be lifted, otherwise false.
1110+ * `preservesValue` is `true` if the summary is value-preserving, and `false` otherwise.
10271111 *
10281112 * Models are lifted to the best type in case the read and store access paths do not
10291113 * contain a field or synthetic field access.
10301114 */
1031- string captureFlow ( ContentDataFlowSummaryTargetApi api , boolean lift ) {
1032- exists ( string input , string output , boolean preservesValue |
1115+ string captureFlow ( ContentDataFlowSummaryTargetApi api , boolean lift , boolean preservesValue ) {
1116+ exists ( string input , string output |
10331117 captureFlow0 ( api , input , output , _, lift ) and
10341118 preservesValue = max ( boolean p | captureFlow0 ( api , input , output , p , lift ) ) and
10351119 result = ContentModelPrinting:: asModel ( api , input , output , preservesValue , lift )
10361120 )
10371121 }
1122+
1123+ /**
1124+ * Gets the content based summary model(s) of the API `api` (if there is flow from a parameter to
1125+ * the return value or a parameter). `lift` is true, if the model should be lifted, otherwise false.
1126+ *
1127+ * Models are lifted to the best type in case the read and store access paths do not
1128+ * contain a field or synthetic field access.
1129+ */
1130+ string captureFlow ( ContentDataFlowSummaryTargetApi api , boolean lift ) {
1131+ result = captureFlow ( api , lift , _)
1132+ }
10381133 }
10391134
10401135 /**
@@ -1046,17 +1141,19 @@ module MakeModelGenerator<
10461141 * generate flow summaries using the heuristic based summary generator.
10471142 */
10481143 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 ) )
1144+ exists ( boolean preservesValue |
1145+ result = ContentSensitive:: captureFlow ( api , lift , preservesValue )
10541146 or
1055- api0 .lift ( ) = api .lift ( ) and
1056- exists ( ContentSensitive:: captureFlow ( api0 , true ) )
1057- ) and
1058- result = Heuristic:: captureFlow ( api ) and
1059- lift = true
1147+ not exists ( DataFlowSummaryTargetApi api0 |
1148+ ( api0 = api or api .lift ( ) = api0 ) and
1149+ exists ( ContentSensitive:: captureFlow ( api0 , false , preservesValue ) )
1150+ or
1151+ api0 .lift ( ) = api .lift ( ) and
1152+ exists ( ContentSensitive:: captureFlow ( api0 , true , preservesValue ) )
1153+ ) and
1154+ result = Heuristic:: captureFlow ( api , preservesValue ) and
1155+ lift = true
1156+ )
10601157 }
10611158
10621159 /**
0 commit comments