9
9
private import FlowSummaryImplSpecific
10
10
private import DataFlowImplSpecific:: Private
11
11
private import DataFlowImplSpecific:: Public
12
+ private import DataFlowImplCommon as DataFlowImplCommon
12
13
13
14
/** Provides classes and predicates for defining flow summaries. */
14
15
module Public {
@@ -178,7 +179,6 @@ module Public {
178
179
*/
179
180
module Private {
180
181
private import Public
181
- private import DataFlowImplCommon as DataFlowImplCommon
182
182
183
183
newtype TSummaryComponent =
184
184
TContentSummaryComponent ( Content c ) or
@@ -580,6 +580,14 @@ module Private {
580
580
* summaries into a `SummarizedCallable`s.
581
581
*/
582
582
module External {
583
+ /** Holds if `spec` is a relevant external specification. */
584
+ private predicate relevantSpec ( string spec ) {
585
+ summaryElement ( _, spec , _, _) or
586
+ summaryElement ( _, _, spec , _) or
587
+ sourceElement ( _, spec , _) or
588
+ sinkElement ( _, spec , _)
589
+ }
590
+
583
591
/** Holds if the `n`th component of specification `s` is `c`. */
584
592
predicate specSplit ( string s , string c , int n ) { relevantSpec ( s ) and s .splitAt ( " of " , n ) = c }
585
593
@@ -629,6 +637,8 @@ module Private {
629
637
or
630
638
exists ( int pos | parseParam ( c , pos ) and result = SummaryComponent:: parameter ( pos ) )
631
639
or
640
+ c = "ReturnValue" and result = SummaryComponent:: return ( getReturnValueKind ( ) )
641
+ or
632
642
result = interpretComponentSpecific ( c )
633
643
)
634
644
}
@@ -664,13 +674,13 @@ module Private {
664
674
}
665
675
666
676
private class SummarizedCallableExternal extends SummarizedCallable {
667
- SummarizedCallableExternal ( ) { externalSummary ( this , _, _, _) }
677
+ SummarizedCallableExternal ( ) { summaryElement ( this , _, _, _) }
668
678
669
679
override predicate propagatesFlow (
670
680
SummaryComponentStack input , SummaryComponentStack output , boolean preservesValue
671
681
) {
672
682
exists ( string inSpec , string outSpec , string kind |
673
- externalSummary ( this , inSpec , outSpec , kind ) and
683
+ summaryElement ( this , inSpec , outSpec , kind ) and
674
684
interpretSpec ( inSpec , 0 , input ) and
675
685
interpretSpec ( outSpec , 0 , output )
676
686
|
@@ -686,6 +696,111 @@ module Private {
686
696
specSplit ( spec , c , _) and
687
697
not exists ( interpretComponent ( c ) )
688
698
}
699
+
700
+ private predicate inputNeedsReference ( string c ) {
701
+ c = "Argument" or
702
+ parseArg ( c , _)
703
+ }
704
+
705
+ private predicate outputNeedsReference ( string c ) {
706
+ c = "Argument" or
707
+ parseArg ( c , _) or
708
+ c = "ReturnValue"
709
+ }
710
+
711
+ private predicate sourceElementRef ( InterpretNode ref , string output , string kind ) {
712
+ exists ( SourceOrSinkElement e |
713
+ sourceElement ( e , output , kind ) and
714
+ if outputNeedsReference ( specLast ( output ) )
715
+ then e = ref .getCallTarget ( )
716
+ else e = ref .asElement ( )
717
+ )
718
+ }
719
+
720
+ private predicate sinkElementRef ( InterpretNode ref , string input , string kind ) {
721
+ exists ( SourceOrSinkElement e |
722
+ sinkElement ( e , input , kind ) and
723
+ if inputNeedsReference ( specLast ( input ) )
724
+ then e = ref .getCallTarget ( )
725
+ else e = ref .asElement ( )
726
+ )
727
+ }
728
+
729
+ private predicate interpretOutput ( string output , int idx , InterpretNode ref , InterpretNode node ) {
730
+ sourceElementRef ( ref , output , _) and
731
+ specLength ( output , idx ) and
732
+ node = ref
733
+ or
734
+ exists ( InterpretNode mid , string c |
735
+ interpretOutput ( output , idx + 1 , ref , mid ) and
736
+ specSplit ( output , c , idx )
737
+ |
738
+ exists ( int pos |
739
+ node .asNode ( )
740
+ .( PostUpdateNode )
741
+ .getPreUpdateNode ( )
742
+ .( ArgumentNode )
743
+ .argumentOf ( mid .asCall ( ) , pos )
744
+ |
745
+ c = "Argument" or parseArg ( c , pos )
746
+ )
747
+ or
748
+ exists ( int pos | node .asNode ( ) .( ParameterNode ) .isParameterOf ( mid .asCallable ( ) , pos ) |
749
+ c = "Parameter" or parseParam ( c , pos )
750
+ )
751
+ or
752
+ c = "ReturnValue" and
753
+ node .asNode ( ) = getAnOutNode ( mid .asCall ( ) , getReturnValueKind ( ) )
754
+ or
755
+ interpretOutputSpecific ( c , mid , node )
756
+ )
757
+ }
758
+
759
+ private predicate interpretInput ( string input , int idx , InterpretNode ref , InterpretNode node ) {
760
+ sinkElementRef ( ref , input , _) and
761
+ specLength ( input , idx ) and
762
+ node = ref
763
+ or
764
+ exists ( InterpretNode mid , string c |
765
+ interpretInput ( input , idx + 1 , ref , mid ) and
766
+ specSplit ( input , c , idx )
767
+ |
768
+ exists ( int pos | node .asNode ( ) .( ArgumentNode ) .argumentOf ( mid .asCall ( ) , pos ) |
769
+ c = "Argument" or parseArg ( c , pos )
770
+ )
771
+ or
772
+ exists ( ReturnNode ret |
773
+ c = "ReturnValue" and
774
+ ret = node .asNode ( ) and
775
+ ret .getKind ( ) = getReturnValueKind ( ) and
776
+ mid .asCallable ( ) = DataFlowImplCommon:: getNodeEnclosingCallable ( ret )
777
+ )
778
+ or
779
+ interpretInputSpecific ( c , mid , node )
780
+ )
781
+ }
782
+
783
+ /**
784
+ * Holds if `node` is specified as a source with the given kind in a CSV flow
785
+ * model.
786
+ */
787
+ predicate isSourceNode ( InterpretNode node , string kind ) {
788
+ exists ( InterpretNode ref , string output |
789
+ sourceElementRef ( ref , output , kind ) and
790
+ interpretOutput ( output , 0 , ref , node )
791
+ )
792
+ }
793
+
794
+ /**
795
+ * Holds if `node` is specified as a sink with the given kind in a CSV flow
796
+ * model.
797
+ */
798
+ predicate isSinkNode ( InterpretNode node , string kind ) {
799
+ exists ( InterpretNode ref , string input |
800
+ sinkElementRef ( ref , input , kind ) and
801
+ interpretInput ( input , 0 , ref , node )
802
+ )
803
+ }
689
804
}
690
805
691
806
/** Provides a query predicate for outputting a set of relevant flow summaries. */
0 commit comments