@@ -567,7 +567,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
567567 ) {
568568 sourceNode ( node ) and
569569 ( if hasSourceCallCtx ( ) then cc = ccSomeCall ( ) else cc = ccNone ( ) ) and
570- summaryCtx = TSummaryCtxNone ( ) and
570+ summaryCtx . isSourceCtx ( ) and
571571 t = getNodeTyp ( node ) and
572572 ap instanceof ApNil and
573573 apa = getApprox ( ap ) and
@@ -611,9 +611,11 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
611611 not Config:: getAFeature ( ) instanceof FeatureEqualSourceSinkCallContext
612612 or
613613 // flow into a callable with summary context (non-linear recursion)
614- fwdFlowInFlowThrough ( node , cc , t , ap , stored ) and
615- apa = getApprox ( ap ) and
616- summaryCtx = TSummaryCtxSome ( node , t , ap , stored )
614+ exists ( boolean mustReturn |
615+ fwdFlowInFlowThrough ( node , cc , t , ap , stored , mustReturn ) and
616+ apa = getApprox ( ap ) and
617+ summaryCtx = TSummaryCtxSome ( node , t , ap , stored , mustReturn )
618+ )
617619 or
618620 // flow out of a callable
619621 fwdFlowOut ( _, _, node , cc , summaryCtx , t , ap , stored ) and
@@ -630,9 +632,10 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
630632
631633 private newtype TSummaryCtx =
632634 TSummaryCtxNone ( ) or
633- TSummaryCtxSome ( ParamNd p , Typ t , Ap ap , TypOption stored ) {
634- fwdFlowInFlowThrough ( p , _, t , ap , stored )
635- }
635+ TSummaryCtxSome ( ParamNd p , Typ t , Ap ap , TypOption stored , Boolean mustReturn ) {
636+ fwdFlowInFlowThrough ( p , _, t , ap , stored , mustReturn )
637+ } or
638+ TSummaryCtxSource ( Boolean mustEscape )
636639
637640 /**
638641 * A context for generating flow summaries. This represents flow entry through
@@ -644,6 +647,55 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
644647 abstract string toString ( ) ;
645648
646649 abstract Location getLocation ( ) ;
650+
651+ /**
652+ * Holds if this context is the unique context used at flow sources.
653+ */
654+ predicate isSourceCtx ( ) {
655+ exists ( boolean strict |
656+ Stage1:: hasFeatureEscapesSourceCallContext ( strict ) and
657+ this = TSummaryCtxSource ( strict )
658+ )
659+ or
660+ not Stage1:: hasFeatureEscapesSourceCallContext ( _) and
661+ this = TSummaryCtxNone ( )
662+ }
663+
664+ pragma [ nomagic]
665+ private predicate isSome ( boolean mustReturn ) {
666+ this = TSummaryCtxSome ( _, _, _, _, mustReturn )
667+ }
668+
669+ /**
670+ * Holds if this context is valid as a flow-in context when no flow-through is possible.
671+ */
672+ predicate isValidForFlowInNoThrough ( ) {
673+ this = TSummaryCtxNone ( )
674+ or
675+ this .isSome ( false )
676+ }
677+
678+ /**
679+ * Holds if this context is valid as a flow-in context when flow-through is possible.
680+ *
681+ * The boolean `mustReturn` indicates whether flow must return.
682+ */
683+ predicate isValidForFlowThrough ( boolean mustReturn ) {
684+ this = TSummaryCtxSource ( _) and
685+ mustReturn = true
686+ or
687+ this = TSummaryCtxNone ( ) and
688+ mustReturn = false
689+ or
690+ this .isSome ( mustReturn )
691+ }
692+
693+ /** Holds if this context is valid as a sink context. */
694+ predicate isASinkCtx ( ) {
695+ this .isValidForFlowInNoThrough ( )
696+ or
697+ this = TSummaryCtxSource ( false )
698+ }
647699 }
648700
649701 /** A summary context from which no flow summary can be generated. */
@@ -659,20 +711,43 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
659711 private Typ t ;
660712 private Ap ap ;
661713 private TypOption stored ;
714+ private boolean mustReturn ;
662715
663- SummaryCtxSome ( ) { this = TSummaryCtxSome ( p , t , ap , stored ) }
716+ SummaryCtxSome ( ) { this = TSummaryCtxSome ( p , t , ap , stored , mustReturn ) }
664717
665718 ParamNd getParamNode ( ) { result = p }
666719
667720 private string ppTyp ( ) { result = t .toString ( ) and result != "" }
668721
722+ private string ppMustReturn ( ) {
723+ if mustReturn = true then result = " <mustReturn>" else result = ""
724+ }
725+
669726 override string toString ( ) {
670- result = p + concat ( " : " + this .ppTyp ( ) ) + " " + ap + ppStored ( stored )
727+ result =
728+ p + concat ( " : " + this .ppTyp ( ) ) + " " + ap + ppStored ( stored ) + this .ppMustReturn ( )
671729 }
672730
673731 override Location getLocation ( ) { result = p .getLocation ( ) }
674732 }
675733
734+ /**
735+ * A special summary context that is used when the flow feature
736+ * `FeatureEscapesSourceCallContext(OrEqualSourceSinkCallContext)`
737+ * is enabled.
738+ */
739+ private class SummaryCtxSource extends SummaryCtx , TSummaryCtxSource {
740+ private boolean mustEscape ;
741+
742+ SummaryCtxSource ( ) { this = TSummaryCtxSource ( mustEscape ) }
743+
744+ override string toString ( ) {
745+ if mustEscape = true then result = "<source-must-escape>" else result = "<source>"
746+ }
747+
748+ override Location getLocation ( ) { result .hasLocationInfo ( "" , 0 , 0 , 0 , 0 ) }
749+ }
750+
676751 private predicate fwdFlowJump ( Nd node , Typ t , Ap ap , TypOption stored ) {
677752 exists ( Nd mid |
678753 fwdFlow ( mid , _, _, t , ap , stored ) and
@@ -917,7 +992,10 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
917992 private predicate fwdFlowInNoFlowThrough (
918993 ParamNd p , CcCall innercc , Typ t , Ap ap , TypOption stored
919994 ) {
920- FwdFlowInNoThrough:: fwdFlowIn ( _, _, _, p , _, innercc , _, t , ap , stored , _)
995+ exists ( SummaryCtx summaryCtx |
996+ FwdFlowInNoThrough:: fwdFlowIn ( _, _, _, p , _, innercc , summaryCtx , t , ap , stored , _) and
997+ summaryCtx .isValidForFlowInNoThrough ( )
998+ )
921999 }
9221000
9231001 private predicate top ( ) { any ( ) }
@@ -926,9 +1004,12 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
9261004
9271005 pragma [ nomagic]
9281006 private predicate fwdFlowInFlowThrough (
929- ParamNd p , CcCall innercc , Typ t , Ap ap , TypOption stored
1007+ ParamNd p , CcCall innercc , Typ t , Ap ap , TypOption stored , boolean mustReturn
9301008 ) {
931- FwdFlowInThrough:: fwdFlowIn ( _, _, _, p , _, innercc , _, t , ap , stored , _)
1009+ exists ( SummaryCtx outerSummaryCtx |
1010+ FwdFlowInThrough:: fwdFlowIn ( _, _, _, p , _, innercc , outerSummaryCtx , t , ap , stored , _) and
1011+ outerSummaryCtx .isValidForFlowThrough ( mustReturn )
1012+ )
9321013 }
9331014
9341015 pragma [ nomagic]
@@ -999,7 +1080,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
9991080 TypOption stored
10001081 ) {
10011082 exists ( RetNd ret , CcNoCall innercc , boolean allowsFieldFlow |
1002- fwdFlowIntoRet ( ret , innercc , summaryCtx , t , ap , stored ) and
1083+ fwdFlowIntoRet ( ret , innercc , _, t , ap , stored ) and
1084+ summaryCtx = TSummaryCtxNone ( ) and
10031085 fwdFlowOutValidEdge ( call , ret , innercc , inner , out , outercc , allowsFieldFlow ) and
10041086 if allowsFieldFlow = false then ap instanceof ApNil else any ( )
10051087 )
@@ -1090,7 +1172,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
10901172 instanceofCcCall ( ccc ) and
10911173 fwdFlow ( pragma [ only_bind_into ] ( ret ) , ccc , summaryCtx , t , ap , stored ) and
10921174 summaryCtx =
1093- TSummaryCtxSome ( pragma [ only_bind_into ] ( p ) , _, pragma [ only_bind_into ] ( argAp ) , _) and
1175+ TSummaryCtxSome ( pragma [ only_bind_into ] ( p ) , _, pragma [ only_bind_into ] ( argAp ) , _, _ ) and
10941176 kind = ret .getKind ( ) and
10951177 Stage1:: parameterFlowThroughAllowed ( p , kind ) and
10961178 PrevStage:: returnMayFlowThrough ( ret , kind )
@@ -1116,9 +1198,10 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
11161198 pragma [ nomagic]
11171199 private predicate fwdFlowIsEntered0 (
11181200 Call call , ArgNd arg , Cc cc , CcCall innerCc , SummaryCtx summaryCtx , ParamNd p , Typ t ,
1119- Ap ap , TypOption stored
1201+ Ap ap , TypOption stored , boolean mustReturn
11201202 ) {
1121- FwdFlowInThrough:: fwdFlowIn ( call , arg , _, p , cc , innerCc , summaryCtx , t , ap , stored , _)
1203+ FwdFlowInThrough:: fwdFlowIn ( call , arg , _, p , cc , innerCc , summaryCtx , t , ap , stored , _) and
1204+ summaryCtx .isValidForFlowThrough ( mustReturn )
11221205 }
11231206
11241207 /**
@@ -1130,9 +1213,9 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
11301213 Call call , ArgNd arg , Cc cc , CcCall innerCc , SummaryCtx summaryCtx ,
11311214 SummaryCtxSome innerSummaryCtx
11321215 ) {
1133- exists ( ParamNd p , Typ t , Ap ap , TypOption stored |
1134- fwdFlowIsEntered0 ( call , arg , cc , innerCc , summaryCtx , p , t , ap , stored ) and
1135- innerSummaryCtx = TSummaryCtxSome ( p , t , ap , stored )
1216+ exists ( ParamNd p , Typ t , Ap ap , TypOption stored , boolean mustReturn |
1217+ fwdFlowIsEntered0 ( call , arg , cc , innerCc , summaryCtx , p , t , ap , stored , mustReturn ) and
1218+ innerSummaryCtx = TSummaryCtxSome ( p , t , ap , stored , mustReturn )
11361219 )
11371220 }
11381221
@@ -1160,7 +1243,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
11601243 TypOption argStored , Ap ap
11611244 ) {
11621245 exists ( Call call , boolean allowsFieldFlow |
1163- returnFlowsThrough0 ( call , ccc , ap , ret , TSummaryCtxSome ( p , argT , argAp , argStored ) ) and
1246+ returnFlowsThrough0 ( call , ccc , ap , ret , TSummaryCtxSome ( p , argT , argAp , argStored , _ ) ) and
11641247 flowThroughOutOfCall ( call , ret , _, allowsFieldFlow ) and
11651248 pos = ret .getReturnPosition ( ) and
11661249 if allowsFieldFlow = false then ap instanceof ApNil else any ( )
@@ -1216,7 +1299,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
12161299
12171300 pragma [ nomagic]
12181301 private predicate revFlow0 ( Nd node , ReturnCtx returnCtx , ApOption returnAp , Ap ap ) {
1219- fwdFlow ( node , _, _ , _, ap , _) and
1302+ fwdFlow ( node , _, any ( SummaryCtx sinkCtx | sinkCtx . isASinkCtx ( ) ) , _, ap , _) and
12201303 sinkNode ( node ) and
12211304 (
12221305 if hasSinkCallCtx ( )
@@ -1490,7 +1573,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
14901573 exists ( Ap ap0 |
14911574 parameterMayFlowThrough ( p , _) and
14921575 revFlow ( n , TReturnCtxMaybeFlowThrough ( _) , _, ap0 ) and
1493- fwdFlow ( n , any ( CcCall ccc ) , TSummaryCtxSome ( p , _, ap , _) , _, ap0 , _)
1576+ fwdFlow ( n , any ( CcCall ccc ) , TSummaryCtxSome ( p , _, ap , _, _ ) , _, ap0 , _)
14941577 )
14951578 }
14961579
@@ -1962,6 +2045,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
19622045 private string ppSummaryCtx ( ) {
19632046 summaryCtx instanceof SummaryCtxNone and result = ""
19642047 or
2048+ result = " " + summaryCtx .( SummaryCtxSource )
2049+ or
19652050 summaryCtx instanceof SummaryCtxSome and
19662051 result = " <" + summaryCtx + ">"
19672052 }
@@ -1983,14 +2068,15 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
19832068 override predicate isSource ( ) {
19842069 sourceNode ( node ) and
19852070 ( if hasSourceCallCtx ( ) then cc = ccSomeCall ( ) else cc = ccNone ( ) ) and
1986- summaryCtx = TSummaryCtxNone ( ) and
2071+ summaryCtx . isSourceCtx ( ) and
19872072 t = getNodeTyp ( node ) and
19882073 ap instanceof ApNil
19892074 }
19902075
19912076 predicate isAtSink ( ) {
19922077 sinkNode ( node ) and
19932078 ap instanceof ApNil and
2079+ summaryCtx .isASinkCtx ( ) and
19942080 // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall`
19952081 // is exactly what we need to check.
19962082 // For `FeatureEqualSourceSinkCallContext` the initial call
@@ -2042,10 +2128,12 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
20422128 override predicate isSource ( ) { sourceNode ( node ) }
20432129 }
20442130
2045- bindingset [ p, t, ap, stored]
2131+ bindingset [ p, t, ap, stored, mustReturn ]
20462132 pragma [ inline_late]
2047- private SummaryCtxSome mkSummaryCtxSome ( ParamNd p , Typ t , Ap ap , TypOption stored ) {
2048- result = TSummaryCtxSome ( p , t , ap , stored )
2133+ private SummaryCtxSome mkSummaryCtxSome (
2134+ ParamNd p , Typ t , Ap ap , TypOption stored , boolean mustReturn
2135+ ) {
2136+ result = TSummaryCtxSome ( p , t , ap , stored , mustReturn )
20492137 }
20502138
20512139 pragma [ nomagic]
@@ -2055,11 +2143,15 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
20552143 ) {
20562144 FwdFlowInNoThrough:: fwdFlowIn ( _, arg , _, p , outercc , innercc , outerSummaryCtx , t , ap ,
20572145 stored , _) and
2146+ outerSummaryCtx .isValidForFlowInNoThrough ( ) and
20582147 innerSummaryCtx = TSummaryCtxNone ( )
20592148 or
2060- FwdFlowInThrough:: fwdFlowIn ( _, arg , _, p , outercc , innercc , outerSummaryCtx , t , ap ,
2061- stored , _) and
2062- innerSummaryCtx = mkSummaryCtxSome ( p , t , ap , stored )
2149+ exists ( boolean mustReturn |
2150+ FwdFlowInThrough:: fwdFlowIn ( _, arg , _, p , outercc , innercc , outerSummaryCtx , t , ap ,
2151+ stored , _) and
2152+ outerSummaryCtx .isValidForFlowThrough ( mustReturn ) and
2153+ innerSummaryCtx = mkSummaryCtxSome ( p , t , ap , stored , mustReturn )
2154+ )
20632155 }
20642156
20652157 pragma [ nomagic]
@@ -2098,7 +2190,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
20982190 |
20992191 fwdFlowThroughStep0 ( call , arg , cc , ccc , summaryCtx , t , ap , stored , ret ,
21002192 innerSummaryCtx ) and
2101- innerSummaryCtx = TSummaryCtxSome ( p , innerArgT , innerArgAp , innerArgStored ) and
2193+ innerSummaryCtx = TSummaryCtxSome ( p , innerArgT , innerArgAp , innerArgStored , _ ) and
21022194 pn1 = mkPathNode ( arg , cc , summaryCtx , innerArgT , innerArgAp , innerArgStored ) and
21032195 pn2 =
21042196 typeStrengthenToPathNode ( p , ccc , innerSummaryCtx , innerArgT , innerArgAp ,
@@ -2212,11 +2304,14 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
22122304 )
22132305 or
22142306 // flow out of a callable
2215- exists ( RetNd ret , CcNoCall innercc , boolean allowsFieldFlow |
2216- pn1 = TPathNodeMid ( ret , innercc , summaryCtx , t , ap , stored ) and
2217- fwdFlowIntoRet ( ret , innercc , summaryCtx , t , ap , stored ) and
2307+ exists (
2308+ RetNd ret , CcNoCall innercc , SummaryCtx innerSummaryCtx , boolean allowsFieldFlow
2309+ |
2310+ pn1 = TPathNodeMid ( ret , innercc , innerSummaryCtx , t , ap , stored ) and
2311+ fwdFlowIntoRet ( ret , innercc , innerSummaryCtx , t , ap , stored ) and
22182312 fwdFlowOutValidEdge ( _, ret , innercc , _, node , cc , allowsFieldFlow ) and
22192313 label = "" and
2314+ summaryCtx = TSummaryCtxNone ( ) and
22202315 if allowsFieldFlow = false then ap instanceof ApNil else any ( )
22212316 )
22222317 }
0 commit comments