@@ -128,7 +128,7 @@ abstract class Configuration extends string {
128128 * Holds if an arbitrary number of implicit read steps of content `c` may be
129129 * taken at `node`.
130130 */
131- predicate allowImplicitRead ( Node node , Content c ) { none ( ) }
131+ predicate allowImplicitRead ( Node node , ContentSet c ) { none ( ) }
132132
133133 /**
134134 * Gets the virtual dispatch branching limit when calculating field flow.
@@ -525,8 +525,9 @@ private predicate additionalJumpStateStep(
525525 )
526526}
527527
528- private predicate read ( NodeEx node1 , Content c , NodeEx node2 , Configuration config ) {
529- read ( node1 .asNode ( ) , c , node2 .asNode ( ) ) and
528+ pragma [ nomagic]
529+ private predicate readSet ( NodeEx node1 , ContentSet c , NodeEx node2 , Configuration config ) {
530+ readSet ( node1 .asNode ( ) , c , node2 .asNode ( ) ) and
530531 stepFilter ( node1 , node2 , config )
531532 or
532533 exists ( Node n |
@@ -536,12 +537,44 @@ private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration conf
536537 )
537538}
538539
540+ // inline to reduce fan-out via `getAReadContent`
541+ pragma [ inline]
542+ private predicate read ( NodeEx node1 , Content c , NodeEx node2 , Configuration config ) {
543+ exists ( ContentSet cs |
544+ readSet ( node1 , cs , node2 , config ) and
545+ c = cs .getAReadContent ( )
546+ )
547+ }
548+
549+ // inline to reduce fan-out via `getAReadContent`
550+ pragma [ inline]
551+ private predicate clearsContentEx ( NodeEx n , Content c ) {
552+ exists ( ContentSet cs |
553+ clearsContentCached ( n .asNode ( ) , cs ) and
554+ c = cs .getAReadContent ( )
555+ )
556+ }
557+
558+ pragma [ nomagic]
559+ private predicate storeSet (
560+ NodeEx node1 , ContentSet c , NodeEx node2 , DataFlowType contentType , DataFlowType containerType ,
561+ Configuration config
562+ ) {
563+ storeSet ( node1 .asNode ( ) , c , node2 .asNode ( ) , contentType , containerType ) and
564+ stepFilter ( node1 , node2 , config ) and
565+ read ( _, c .getAStoreContent ( ) , _, config )
566+ }
567+
568+ // inline to reduce fan-out via `getAStoreContent`
569+ pragma [ inline]
539570private predicate store (
540- NodeEx node1 , TypedContent tc , NodeEx node2 , DataFlowType contentType , Configuration config
571+ NodeEx node1 , Content c , NodeEx node2 , DataFlowType contentType , DataFlowType containerType ,
572+ Configuration config
541573) {
542- store ( node1 .asNode ( ) , tc , node2 .asNode ( ) , contentType ) and
543- read ( _, tc .getContent ( ) , _, config ) and
544- stepFilter ( node1 , node2 , config )
574+ exists ( ContentSet cs |
575+ storeSet ( node1 , cs , node2 , contentType , containerType , config ) and
576+ c = cs .getAStoreContent ( )
577+ )
545578}
546579
547580pragma [ nomagic]
@@ -609,13 +642,13 @@ private module Stage1 {
609642 exists ( NodeEx mid |
610643 useFieldFlow ( config ) and
611644 fwdFlow ( mid , cc , config ) and
612- store ( mid , _, node , _, config )
645+ storeSet ( mid , _, node , _ , _, config )
613646 )
614647 or
615648 // read
616- exists ( Content c |
617- fwdFlowRead ( c , node , cc , config ) and
618- fwdFlowConsCand ( c , config )
649+ exists ( ContentSet c |
650+ fwdFlowReadSet ( c , node , cc , config ) and
651+ fwdFlowConsCandSet ( c , config )
619652 )
620653 or
621654 // flow into a callable
@@ -639,10 +672,10 @@ private module Stage1 {
639672 private predicate fwdFlow ( NodeEx node , Configuration config ) { fwdFlow ( node , _, config ) }
640673
641674 pragma [ nomagic]
642- private predicate fwdFlowRead ( Content c , NodeEx node , Cc cc , Configuration config ) {
675+ private predicate fwdFlowReadSet ( ContentSet c , NodeEx node , Cc cc , Configuration config ) {
643676 exists ( NodeEx mid |
644677 fwdFlow ( mid , cc , config ) and
645- read ( mid , c , node , config )
678+ readSet ( mid , c , node , config )
646679 )
647680 }
648681
@@ -651,15 +684,23 @@ private module Stage1 {
651684 */
652685 pragma [ nomagic]
653686 private predicate fwdFlowConsCand ( Content c , Configuration config ) {
654- exists ( NodeEx mid , NodeEx node , TypedContent tc |
687+ exists ( NodeEx mid , NodeEx node |
655688 not fullBarrier ( node , config ) and
656689 useFieldFlow ( config ) and
657690 fwdFlow ( mid , _, config ) and
658- store ( mid , tc , node , _, config ) and
659- c = tc .getContent ( )
691+ store ( mid , c , node , _, _, config )
660692 )
661693 }
662694
695+ /**
696+ * Holds if `c` may be interpreted in a read as the target of some store,
697+ * in the flow covered by `fwdFlow`.
698+ */
699+ pragma [ nomagic]
700+ private predicate fwdFlowConsCandSet ( ContentSet c , Configuration config ) {
701+ fwdFlowConsCand ( c .getAReadContent ( ) , config )
702+ }
703+
663704 pragma [ nomagic]
664705 private predicate fwdFlowReturnPosition ( ReturnPosition pos , Cc cc , Configuration config ) {
665706 exists ( RetNodeEx ret |
@@ -746,15 +787,15 @@ private module Stage1 {
746787 )
747788 or
748789 // store
749- exists ( Content c |
750- revFlowStore ( c , node , toReturn , config ) and
751- revFlowConsCand ( c , config )
790+ exists ( ContentSet c |
791+ revFlowStoreSet ( c , node , toReturn , config ) and
792+ revFlowConsCandSet ( c , config )
752793 )
753794 or
754795 // read
755- exists ( NodeEx mid , Content c |
756- read ( node , c , mid , config ) and
757- fwdFlowConsCand ( c , pragma [ only_bind_into ] ( config ) ) and
796+ exists ( NodeEx mid , ContentSet c |
797+ readSet ( node , c , mid , config ) and
798+ fwdFlowConsCandSet ( c , pragma [ only_bind_into ] ( config ) ) and
758799 revFlow ( mid , toReturn , pragma [ only_bind_into ] ( config ) )
759800 )
760801 or
@@ -789,22 +830,32 @@ private module Stage1 {
789830 }
790831
791832 pragma [ nomagic]
792- private predicate revFlowStore ( Content c , NodeEx node , boolean toReturn , Configuration config ) {
793- exists ( NodeEx mid , TypedContent tc |
833+ private predicate revFlowConsCandSet ( ContentSet c , Configuration config ) {
834+ revFlowConsCand ( c .getAStoreContent ( ) , config )
835+ }
836+
837+ pragma [ nomagic]
838+ private predicate revFlowStoreSet (
839+ ContentSet c , NodeEx node , boolean toReturn , Configuration config
840+ ) {
841+ exists ( NodeEx mid |
794842 revFlow ( mid , toReturn , pragma [ only_bind_into ] ( config ) ) and
795- fwdFlowConsCand ( c , pragma [ only_bind_into ] ( config ) ) and
796- store ( node , tc , mid , _, config ) and
797- c = tc .getContent ( )
843+ fwdFlowConsCandSet ( c , pragma [ only_bind_into ] ( config ) ) and
844+ storeSet ( node , c , mid , _, _, config )
798845 )
799846 }
800847
801848 /**
802849 * Holds if `c` is the target of both a read and a store in the flow covered
803850 * by `revFlow`.
804851 */
852+ pragma [ nomagic]
805853 private predicate revFlowIsReadAndStored ( Content c , Configuration conf ) {
806854 revFlowConsCand ( c , conf ) and
807- revFlowStore ( c , _, _, conf )
855+ exists ( ContentSet cs |
856+ revFlowStoreSet ( cs , _, _, conf ) and
857+ c = cs .getAStoreContent ( )
858+ )
808859 }
809860
810861 pragma [ nomagic]
@@ -889,20 +940,20 @@ private module Stage1 {
889940 NodeEx node1 , Ap ap1 , TypedContent tc , NodeEx node2 , DataFlowType contentType ,
890941 Configuration config
891942 ) {
892- exists ( Content c |
893- revFlowIsReadAndStored ( c , pragma [ only_bind_into ] ( config ) ) and
943+ exists ( Content c , DataFlowType containerType |
944+ revFlowIsReadAndStored ( pragma [ only_bind_into ] ( c ) , pragma [ only_bind_into ] ( config ) ) and
945+ store ( node1 , c , node2 , contentType , containerType , config ) and
894946 revFlow ( node2 , pragma [ only_bind_into ] ( config ) ) and
895- store ( node1 , tc , node2 , contentType , config ) and
896- c = tc .getContent ( ) and
947+ tc = MkTypedContent ( c , containerType ) and
897948 exists ( ap1 )
898949 )
899950 }
900951
901952 pragma [ nomagic]
902953 predicate readStepCand ( NodeEx n1 , Content c , NodeEx n2 , Configuration config ) {
903- revFlowIsReadAndStored ( c , pragma [ only_bind_into ] ( config ) ) and
904- revFlow ( n2 , pragma [ only_bind_into ] ( config ) ) and
905- read ( n1 , c , n2 , pragma [ only_bind_into ] ( config ) )
954+ revFlowIsReadAndStored ( pragma [ only_bind_into ] ( c ) , pragma [ only_bind_into ] ( config ) ) and
955+ read ( n1 , c , n2 , pragma [ only_bind_into ] ( config ) ) and
956+ revFlow ( n2 , pragma [ only_bind_into ] ( config ) )
906957 }
907958
908959 pragma [ nomagic]
@@ -1614,7 +1665,7 @@ private module Stage2 {
16141665 Configuration config
16151666 ) {
16161667 exists ( Ap ap2 , Content c |
1617- store ( node1 , tc , node2 , contentType , config ) and
1668+ PrevStage :: storeStepCand ( node1 , _ , tc , node2 , contentType , config ) and
16181669 revFlowStore ( ap2 , c , ap1 , node1 , _, tc , node2 , _, _, config ) and
16191670 revFlowConsCand ( ap2 , c , ap1 , config )
16201671 )
@@ -1769,9 +1820,9 @@ private module LocalFlowBigStep {
17691820 or
17701821 node .asNode ( ) instanceof OutNodeExt
17711822 or
1772- store ( _, _, node , _, config )
1823+ Stage2 :: storeStepCand ( _ , _, _, node , _, config )
17731824 or
1774- read ( _, _, node , config )
1825+ Stage2 :: readStepCand ( _, _, node , config )
17751826 or
17761827 node instanceof FlowCheckNode
17771828 or
@@ -1792,8 +1843,8 @@ private module LocalFlowBigStep {
17921843 additionalJumpStep ( node , next , config ) or
17931844 flowIntoCallNodeCand1 ( _, node , next , config ) or
17941845 flowOutOfCallNodeCand1 ( _, node , next , config ) or
1795- store ( node , _, next , _, config ) or
1796- read ( node , _, next , config )
1846+ Stage2 :: storeStepCand ( node , _ , _, next , _, config ) or
1847+ Stage2 :: readStepCand ( node , _, next , config )
17971848 )
17981849 or
17991850 exists ( NodeEx next , FlowState s | Stage2:: revFlow ( next , s , config ) |
@@ -1966,7 +2017,24 @@ private module Stage3 {
19662017 private predicate flowIntoCall = flowIntoCallNodeCand2 / 5 ;
19672018
19682019 pragma [ nomagic]
1969- private predicate clear ( NodeEx node , Ap ap ) { ap .isClearedAt ( node .asNode ( ) ) }
2020+ predicate clearSet ( NodeEx node , ContentSet c , Configuration config ) {
2021+ PrevStage:: revFlow ( node , config ) and
2022+ clearsContentCached ( node .asNode ( ) , c )
2023+ }
2024+
2025+ pragma [ nomagic]
2026+ private predicate clearContent ( NodeEx node , Content c , Configuration config ) {
2027+ exists ( ContentSet cs |
2028+ PrevStage:: readStepCand ( _, pragma [ only_bind_into ] ( c ) , _, pragma [ only_bind_into ] ( config ) ) and
2029+ c = cs .getAReadContent ( ) and
2030+ clearSet ( node , cs , pragma [ only_bind_into ] ( config ) )
2031+ )
2032+ }
2033+
2034+ pragma [ nomagic]
2035+ private predicate clear ( NodeEx node , Ap ap , Configuration config ) {
2036+ clearContent ( node , ap .getHead ( ) .getContent ( ) , config )
2037+ }
19702038
19712039 pragma [ nomagic]
19722040 private predicate castingNodeEx ( NodeEx node ) { node .asNode ( ) instanceof CastingNode }
@@ -1975,7 +2043,7 @@ private module Stage3 {
19752043 private predicate filter ( NodeEx node , FlowState state , Ap ap , Configuration config ) {
19762044 exists ( state ) and
19772045 exists ( config ) and
1978- not clear ( node , ap ) and
2046+ not clear ( node , ap , config ) and
19792047 if castingNodeEx ( node ) then compatibleTypes ( node .getDataFlowType ( ) , ap .getType ( ) ) else any ( )
19802048 }
19812049
@@ -2403,7 +2471,7 @@ private module Stage3 {
24032471 Configuration config
24042472 ) {
24052473 exists ( Ap ap2 , Content c |
2406- store ( node1 , tc , node2 , contentType , config ) and
2474+ PrevStage :: storeStepCand ( node1 , _ , tc , node2 , contentType , config ) and
24072475 revFlowStore ( ap2 , c , ap1 , node1 , _, tc , node2 , _, _, config ) and
24082476 revFlowConsCand ( ap2 , c , ap1 , config )
24092477 )
@@ -3231,7 +3299,7 @@ private module Stage4 {
32313299 Configuration config
32323300 ) {
32333301 exists ( Ap ap2 , Content c |
3234- store ( node1 , tc , node2 , contentType , config ) and
3302+ PrevStage :: storeStepCand ( node1 , _ , tc , node2 , contentType , config ) and
32353303 revFlowStore ( ap2 , c , ap1 , node1 , _, tc , node2 , _, _, config ) and
32363304 revFlowConsCand ( ap2 , c , ap1 , config )
32373305 )
@@ -4242,8 +4310,8 @@ private module Subpaths {
42424310 result .isHidden ( ) and
42434311 exists ( NodeEx n1 , NodeEx n2 | n1 = n .getNodeEx ( ) and n2 = result .getNodeEx ( ) |
42444312 localFlowBigStep ( n1 , _, n2 , _, _, _, _, _) or
4245- store ( n1 , _, n2 , _, _) or
4246- read ( n1 , _, n2 , _)
4313+ storeSet ( n1 , _, n2 , _ , _, _) or
4314+ readSet ( n1 , _, n2 , _)
42474315 )
42484316 }
42494317
@@ -4598,7 +4666,7 @@ private module FlowExploration {
45984666 or
45994667 exists ( PartialPathNodeRev mid |
46004668 revPartialPathStep ( mid , node , state , sc1 , sc2 , sc3 , ap , config ) and
4601- not clearsContentCached ( node . asNode ( ) , ap .getHead ( ) ) and
4669+ not clearsContentEx ( node , ap .getHead ( ) ) and
46024670 not fullBarrier ( node , config ) and
46034671 not stateBarrier ( node , state , config ) and
46044672 distSink ( node .getEnclosingCallable ( ) , config ) <= config .explorationLimit ( )
@@ -4614,7 +4682,7 @@ private module FlowExploration {
46144682 partialPathStep ( mid , node , state , cc , sc1 , sc2 , sc3 , ap , config ) and
46154683 not fullBarrier ( node , config ) and
46164684 not stateBarrier ( node , state , config ) and
4617- not clearsContentCached ( node . asNode ( ) , ap .getHead ( ) .getContent ( ) ) and
4685+ not clearsContentEx ( node , ap .getHead ( ) .getContent ( ) ) and
46184686 if node .asNode ( ) instanceof CastingNode
46194687 then compatibleTypes ( node .getDataFlowType ( ) , ap .getType ( ) )
46204688 else any ( )
@@ -4893,10 +4961,11 @@ private module FlowExploration {
48934961 PartialPathNodeFwd mid , PartialAccessPath ap1 , TypedContent tc , NodeEx node ,
48944962 PartialAccessPath ap2
48954963 ) {
4896- exists ( NodeEx midNode , DataFlowType contentType |
4964+ exists ( NodeEx midNode , Content c , DataFlowType contentType , DataFlowType containerType |
48974965 midNode = mid .getNodeEx ( ) and
48984966 ap1 = mid .getAp ( ) and
4899- store ( midNode , tc , node , contentType , mid .getConfiguration ( ) ) and
4967+ store ( midNode , c , node , contentType , containerType , mid .getConfiguration ( ) ) and
4968+ tc = MkTypedContent ( c , containerType ) and
49004969 ap2 .getHead ( ) = tc and
49014970 ap2 .len ( ) = unbindInt ( ap1 .len ( ) + 1 ) and
49024971 compatibleTypes ( ap1 .getType ( ) , contentType )
@@ -4918,10 +4987,11 @@ private module FlowExploration {
49184987 PartialPathNodeFwd mid , PartialAccessPath ap , TypedContent tc , NodeEx node , CallContext cc ,
49194988 Configuration config
49204989 ) {
4921- exists ( NodeEx midNode |
4990+ exists ( NodeEx midNode , Content c |
49224991 midNode = mid .getNodeEx ( ) and
49234992 ap = mid .getAp ( ) and
4924- read ( midNode , tc .getContent ( ) , node , pragma [ only_bind_into ] ( config ) ) and
4993+ read ( midNode , c , node , pragma [ only_bind_into ] ( config ) ) and
4994+ tc .getContent ( ) = c and
49254995 ap .getHead ( ) = tc and
49264996 pragma [ only_bind_into ] ( config ) = mid .getConfiguration ( ) and
49274997 cc = mid .getCallContext ( )
@@ -5171,13 +5241,12 @@ private module FlowExploration {
51715241 private predicate revPartialPathStoreStep (
51725242 PartialPathNodeRev mid , RevPartialAccessPath ap , Content c , NodeEx node , Configuration config
51735243 ) {
5174- exists ( NodeEx midNode , TypedContent tc |
5244+ exists ( NodeEx midNode , DataFlowType contentType , DataFlowType containerType , TypedContent tc |
51755245 midNode = mid .getNodeEx ( ) and
51765246 ap = mid .getAp ( ) and
5177- store ( node , tc , midNode , _, config ) and
5178- ap .getHead ( ) = c and
5179- config = mid .getConfiguration ( ) and
5180- tc .getContent ( ) = c
5247+ store ( node , c , midNode , contentType , containerType , config ) and
5248+ tc = MkTypedContent ( c , containerType ) and
5249+ config = mid .getConfiguration ( )
51815250 )
51825251 }
51835252
0 commit comments