@@ -580,88 +580,112 @@ module Private {
580
580
* summaries into a `SummarizedCallable`s.
581
581
*/
582
582
module External {
583
- /**
584
- * Provides a means of translating an externally (e.g., CSV) defined flow
585
- * summary into a `SummarizedCallable`.
586
- */
587
- abstract class ExternalSummaryCompilation extends string {
588
- bindingset [ this ]
589
- ExternalSummaryCompilation ( ) { any ( ) }
590
-
591
- /** Holds if this flow summary is for callable `c`. */
592
- abstract predicate callable ( DataFlowCallable c , boolean preservesValue ) ;
593
-
594
- /** Holds if the `i`th input component is `c`. */
595
- abstract predicate input ( int i , SummaryComponent c ) ;
596
-
597
- /** Holds if the `i`th output component is `c`. */
598
- abstract predicate output ( int i , SummaryComponent c ) ;
599
-
600
- /**
601
- * Holds if the input components starting from index `i` translate into `suffix`.
602
- */
603
- final predicate translateInput ( int i , SummaryComponentStack suffix ) {
604
- exists ( SummaryComponent comp | this .input ( i , comp ) |
605
- i = max ( int j | this .input ( j , _) ) and
606
- suffix = TSingletonSummaryComponentStack ( comp )
607
- or
608
- exists ( TSummaryComponent head , SummaryComponentStack tail |
609
- this .translateInputCons ( i , head , tail ) and
610
- suffix = TConsSummaryComponentStack ( head , tail )
611
- )
612
- )
613
- }
583
+ /** Holds if the `n`th component of specification `s` is `c`. */
584
+ predicate specSplit ( string s , string c , int n ) { relevantSpec ( s ) and s .splitAt ( " of " , n ) = c }
614
585
615
- final predicate translateInputCons ( int i , SummaryComponent head , SummaryComponentStack tail ) {
616
- this .input ( i , head ) and
617
- this .translateInput ( i + 1 , tail )
618
- }
586
+ /** Holds if specification `s` has length `len`. */
587
+ predicate specLength ( string s , int len ) { len = 1 + max ( int n | specSplit ( s , _, n ) ) }
619
588
620
- /**
621
- * Holds if the output components starting from index `i` translate into `suffix`.
622
- */
623
- predicate translateOutput ( int i , SummaryComponentStack suffix ) {
624
- exists ( SummaryComponent comp | this .output ( i , comp ) |
625
- i = max ( int j | this .output ( j , _) ) and
626
- suffix = TSingletonSummaryComponentStack ( comp )
627
- or
628
- exists ( TSummaryComponent head , SummaryComponentStack tail |
629
- this .translateOutputCons ( i , head , tail ) and
630
- suffix = TConsSummaryComponentStack ( head , tail )
631
- )
589
+ /** Gets the last component of specification `s`. */
590
+ string specLast ( string s ) {
591
+ exists ( int len |
592
+ specLength ( s , len ) and
593
+ specSplit ( s , result , len - 1 )
594
+ )
595
+ }
596
+
597
+ /** Holds if specification component `c` parses as parameter `n`. */
598
+ predicate parseParam ( string c , int n ) {
599
+ specSplit ( _, c , _) and
600
+ (
601
+ c .regexpCapture ( "Parameter\\[([-0-9]+)\\]" , 1 ) .toInt ( ) = n
602
+ or
603
+ exists ( int n1 , int n2 |
604
+ c .regexpCapture ( "Parameter\\[([-0-9]+)\\.\\.([0-9]+)\\]" , 1 ) .toInt ( ) = n1 and
605
+ c .regexpCapture ( "Parameter\\[([-0-9]+)\\.\\.([0-9]+)\\]" , 2 ) .toInt ( ) = n2 and
606
+ n = [ n1 .. n2 ]
632
607
)
633
- }
608
+ )
609
+ }
634
610
635
- predicate translateOutputCons ( int i , SummaryComponent head , SummaryComponentStack tail ) {
636
- this .output ( i , head ) and
637
- this .translateOutput ( i + 1 , tail )
638
- }
611
+ /** Holds if specification component `c` parses as argument `n`. */
612
+ predicate parseArg ( string c , int n ) {
613
+ specSplit ( _, c , _) and
614
+ (
615
+ c .regexpCapture ( "Argument\\[([-0-9]+)\\]" , 1 ) .toInt ( ) = n
616
+ or
617
+ exists ( int n1 , int n2 |
618
+ c .regexpCapture ( "Argument\\[([-0-9]+)\\.\\.([0-9]+)\\]" , 1 ) .toInt ( ) = n1 and
619
+ c .regexpCapture ( "Argument\\[([-0-9]+)\\.\\.([0-9]+)\\]" , 2 ) .toInt ( ) = n2 and
620
+ n = [ n1 .. n2 ]
621
+ )
622
+ )
639
623
}
640
624
641
- private class ExternalRequiredSummaryComponentStack extends RequiredSummaryComponentStack {
642
- private SummaryComponent head ;
625
+ private SummaryComponent interpretComponent ( string c ) {
626
+ specSplit ( _, c , _) and
627
+ (
628
+ exists ( int pos | parseArg ( c , pos ) and result = SummaryComponent:: argument ( pos ) )
629
+ or
630
+ exists ( int pos | parseParam ( c , pos ) and result = SummaryComponent:: parameter ( pos ) )
631
+ or
632
+ result = interpretComponentSpecific ( c )
633
+ )
634
+ }
643
635
644
- ExternalRequiredSummaryComponentStack ( ) {
645
- any ( ExternalSummaryCompilation s ) .translateInputCons ( _, head , this ) or
646
- any ( ExternalSummaryCompilation s ) .translateOutputCons ( _, head , this )
647
- }
636
+ private predicate interpretSpec ( string spec , int idx , SummaryComponentStack stack ) {
637
+ exists ( string c |
638
+ relevantSpec ( spec ) and
639
+ specLength ( spec , idx + 1 ) and
640
+ specSplit ( spec , c , idx ) and
641
+ stack = SummaryComponentStack:: singleton ( interpretComponent ( c ) )
642
+ )
643
+ or
644
+ exists ( SummaryComponent head , SummaryComponentStack tail |
645
+ interpretSpec ( spec , idx , head , tail ) and
646
+ stack = SummaryComponentStack:: push ( head , tail )
647
+ )
648
+ }
648
649
649
- override predicate required ( SummaryComponent c ) { c = head }
650
+ private predicate interpretSpec (
651
+ string output , int idx , SummaryComponent head , SummaryComponentStack tail
652
+ ) {
653
+ exists ( string c |
654
+ interpretSpec ( output , idx + 1 , tail ) and
655
+ specSplit ( output , c , idx ) and
656
+ head = interpretComponent ( c )
657
+ )
650
658
}
651
659
652
- class ExternalSummarizedCallableAdaptor extends SummarizedCallable {
653
- ExternalSummarizedCallableAdaptor ( ) { any ( ExternalSummaryCompilation s ) .callable ( this , _) }
660
+ private class MkStack extends RequiredSummaryComponentStack {
661
+ MkStack ( ) { interpretSpec ( _, _, _, this ) }
662
+
663
+ override predicate required ( SummaryComponent c ) { interpretSpec ( _, _, c , this ) }
664
+ }
665
+
666
+ private class SummarizedCallableExternal extends SummarizedCallable {
667
+ SummarizedCallableExternal ( ) { externalSummary ( this , _, _, _) }
654
668
655
669
override predicate propagatesFlow (
656
670
SummaryComponentStack input , SummaryComponentStack output , boolean preservesValue
657
671
) {
658
- exists ( ExternalSummaryCompilation s |
659
- s .callable ( this , preservesValue ) and
660
- s .translateInput ( 0 , input ) and
661
- s .translateOutput ( 0 , output )
672
+ exists ( string inSpec , string outSpec , string kind |
673
+ externalSummary ( this , inSpec , outSpec , kind ) and
674
+ interpretSpec ( inSpec , 0 , input ) and
675
+ interpretSpec ( outSpec , 0 , output )
676
+ |
677
+ kind = "value" and preservesValue = true
678
+ or
679
+ kind = "taint" and preservesValue = false
662
680
)
663
681
}
664
682
}
683
+
684
+ /** Holds if component `c` of specification `spec` cannot be parsed. */
685
+ predicate invalidSpecComponent ( string spec , string c ) {
686
+ specSplit ( spec , c , _) and
687
+ not exists ( interpretComponent ( c ) )
688
+ }
665
689
}
666
690
667
691
/** Provides a query predicate for outputting a set of relevant flow summaries. */
0 commit comments