67
67
import java
68
68
private import semmle.code.java.dataflow.DataFlow:: DataFlow
69
69
private import internal.DataFlowPrivate
70
+ private import internal.FlowSummaryImpl:: Private:: External
70
71
private import FlowSummary
71
72
72
73
/**
@@ -498,10 +499,15 @@ module CsvValidation {
498
499
or
499
500
summaryModel ( _, _, _, _, _, _, input , _, _) and pred = "summary"
500
501
|
501
- specSplit ( input , part , _) and
502
- not part .regexpMatch ( "|ReturnValue|ArrayElement|Element|MapKey|MapValue" ) and
503
- not ( part = "Argument" and pred = "sink" ) and
504
- not parseArg ( part , _) and
502
+ (
503
+ invalidSpecComponent ( input , part ) and
504
+ not part = "" and
505
+ not ( part = "Argument" and pred = "sink" ) and
506
+ not parseArg ( part , _)
507
+ or
508
+ specSplit ( input , part , _) and
509
+ parseParam ( part , _)
510
+ ) and
505
511
msg = "Unrecognized input specification \"" + part + "\" in " + pred + " model."
506
512
)
507
513
or
@@ -510,11 +516,9 @@ module CsvValidation {
510
516
or
511
517
summaryModel ( _, _, _, _, _, _, _, output , _) and pred = "summary"
512
518
|
513
- specSplit ( output , part , _ ) and
514
- not part . regexpMatch ( "|ReturnValue|ArrayElement|Element|MapKey|MapValue" ) and
519
+ invalidSpecComponent ( output , part ) and
520
+ not part = "" and
515
521
not ( part = [ "Argument" , "Parameter" ] and pred = "source" ) and
516
- not parseArg ( part , _) and
517
- not parseParam ( part , _) and
518
522
msg = "Unrecognized output specification \"" + part + "\" in " + pred + " model."
519
523
)
520
524
or
@@ -624,7 +628,11 @@ private predicate sinkElement(Element e, string input, string kind) {
624
628
)
625
629
}
626
630
627
- private predicate summaryElement ( Element e , string input , string output , string kind ) {
631
+ /**
632
+ * Holds if an external flow summary exists for `e` with input specification
633
+ * `input`, output specification `output`, and kind `kind`.
634
+ */
635
+ predicate summaryElement ( Element e , string input , string output , string kind ) {
628
636
exists (
629
637
string namespace , string type , boolean subtypes , string name , string signature , string ext
630
638
|
@@ -633,52 +641,14 @@ private predicate summaryElement(Element e, string input, string output, string
633
641
)
634
642
}
635
643
636
- private string inOutSpec ( ) {
644
+ /** Gets a specification used in a source model, sink model, or summary model. */
645
+ string inOutSpec ( ) {
637
646
sourceModel ( _, _, _, _, _, _, result , _) or
638
647
sinkModel ( _, _, _, _, _, _, result , _) or
639
648
summaryModel ( _, _, _, _, _, _, result , _, _) or
640
649
summaryModel ( _, _, _, _, _, _, _, result , _)
641
650
}
642
651
643
- private predicate specSplit ( string s , string c , int n ) {
644
- inOutSpec ( ) = s and s .splitAt ( " of " , n ) = c
645
- }
646
-
647
- private predicate len ( string s , int len ) { len = 1 + max ( int n | specSplit ( s , _, n ) ) }
648
-
649
- private string getLast ( string s ) {
650
- exists ( int len |
651
- len ( s , len ) and
652
- specSplit ( s , result , len - 1 )
653
- )
654
- }
655
-
656
- private predicate parseParam ( string c , int n ) {
657
- specSplit ( _, c , _) and
658
- (
659
- c .regexpCapture ( "Parameter\\[([-0-9]+)\\]" , 1 ) .toInt ( ) = n
660
- or
661
- exists ( int n1 , int n2 |
662
- c .regexpCapture ( "Parameter\\[([-0-9]+)\\.\\.([0-9]+)\\]" , 1 ) .toInt ( ) = n1 and
663
- c .regexpCapture ( "Parameter\\[([-0-9]+)\\.\\.([0-9]+)\\]" , 2 ) .toInt ( ) = n2 and
664
- n = [ n1 .. n2 ]
665
- )
666
- )
667
- }
668
-
669
- private predicate parseArg ( string c , int n ) {
670
- specSplit ( _, c , _) and
671
- (
672
- c .regexpCapture ( "Argument\\[([-0-9]+)\\]" , 1 ) .toInt ( ) = n
673
- or
674
- exists ( int n1 , int n2 |
675
- c .regexpCapture ( "Argument\\[([-0-9]+)\\.\\.([0-9]+)\\]" , 1 ) .toInt ( ) = n1 and
676
- c .regexpCapture ( "Argument\\[([-0-9]+)\\.\\.([0-9]+)\\]" , 2 ) .toInt ( ) = n2 and
677
- n = [ n1 .. n2 ]
678
- )
679
- )
680
- }
681
-
682
652
private predicate inputNeedsReference ( string c ) {
683
653
c = "Argument" or
684
654
parseArg ( c , _)
@@ -693,7 +663,7 @@ private predicate outputNeedsReference(string c) {
693
663
private predicate sourceElementRef ( Top ref , string output , string kind ) {
694
664
exists ( Element e |
695
665
sourceElement ( e , output , kind ) and
696
- if outputNeedsReference ( getLast ( output ) )
666
+ if outputNeedsReference ( specLast ( output ) )
697
667
then ref .( Call ) .getCallee ( ) .getSourceDeclaration ( ) = e
698
668
else ref = e
699
669
)
@@ -702,7 +672,7 @@ private predicate sourceElementRef(Top ref, string output, string kind) {
702
672
private predicate sinkElementRef ( Top ref , string input , string kind ) {
703
673
exists ( Element e |
704
674
sinkElement ( e , input , kind ) and
705
- if inputNeedsReference ( getLast ( input ) )
675
+ if inputNeedsReference ( specLast ( input ) )
706
676
then ref .( Call ) .getCallee ( ) .getSourceDeclaration ( ) = e
707
677
else ref = e
708
678
)
@@ -711,81 +681,12 @@ private predicate sinkElementRef(Top ref, string input, string kind) {
711
681
private predicate summaryElementRef ( Top ref , string input , string output , string kind ) {
712
682
exists ( Element e |
713
683
summaryElement ( e , input , output , kind ) and
714
- if inputNeedsReference ( getLast ( input ) )
684
+ if inputNeedsReference ( specLast ( input ) )
715
685
then ref .( Call ) .getCallee ( ) .getSourceDeclaration ( ) = e
716
686
else ref = e
717
687
)
718
688
}
719
689
720
- private SummaryComponent interpretComponent ( string c ) {
721
- specSplit ( _, c , _) and
722
- (
723
- exists ( int pos | parseArg ( c , pos ) and result = SummaryComponent:: argument ( pos ) )
724
- or
725
- exists ( int pos | parseParam ( c , pos ) and result = SummaryComponent:: parameter ( pos ) )
726
- or
727
- c = "ReturnValue" and result = SummaryComponent:: return ( )
728
- or
729
- c = "ArrayElement" and result = SummaryComponent:: content ( any ( ArrayContent c0 ) )
730
- or
731
- c = "Element" and result = SummaryComponent:: content ( any ( CollectionContent c0 ) )
732
- or
733
- c = "MapKey" and result = SummaryComponent:: content ( any ( MapKeyContent c0 ) )
734
- or
735
- c = "MapValue" and result = SummaryComponent:: content ( any ( MapValueContent c0 ) )
736
- )
737
- }
738
-
739
- private predicate interpretSpec ( string spec , int idx , SummaryComponentStack stack ) {
740
- exists ( string c |
741
- summaryElement ( _, spec , _, _) or
742
- summaryElement ( _, _, spec , _)
743
- |
744
- len ( spec , idx + 1 ) and
745
- specSplit ( spec , c , idx ) and
746
- stack = SummaryComponentStack:: singleton ( interpretComponent ( c ) )
747
- )
748
- or
749
- exists ( SummaryComponent head , SummaryComponentStack tail |
750
- interpretSpec ( spec , idx , head , tail ) and
751
- stack = SummaryComponentStack:: push ( head , tail )
752
- )
753
- }
754
-
755
- private predicate interpretSpec (
756
- string output , int idx , SummaryComponent head , SummaryComponentStack tail
757
- ) {
758
- exists ( string c |
759
- interpretSpec ( output , idx + 1 , tail ) and
760
- specSplit ( output , c , idx ) and
761
- head = interpretComponent ( c )
762
- )
763
- }
764
-
765
- private class MkStack extends RequiredSummaryComponentStack {
766
- MkStack ( ) { interpretSpec ( _, _, _, this ) }
767
-
768
- override predicate required ( SummaryComponent c ) { interpretSpec ( _, _, c , this ) }
769
- }
770
-
771
- private class SummarizedCallableExternal extends SummarizedCallable {
772
- SummarizedCallableExternal ( ) { summaryElement ( this , _, _, _) }
773
-
774
- override predicate propagatesFlow (
775
- SummaryComponentStack input , SummaryComponentStack output , boolean preservesValue
776
- ) {
777
- exists ( string inSpec , string outSpec , string kind |
778
- summaryElement ( this , inSpec , outSpec , kind ) and
779
- interpretSpec ( inSpec , 0 , input ) and
780
- interpretSpec ( outSpec , 0 , output )
781
- |
782
- kind = "value" and preservesValue = true
783
- or
784
- kind = "taint" and preservesValue = false
785
- )
786
- }
787
- }
788
-
789
690
private newtype TAstOrNode =
790
691
TAst ( Top t ) or
791
692
TNode ( Node n )
@@ -795,7 +696,7 @@ private predicate interpretOutput(string output, int idx, Top ref, TAstOrNode no
795
696
sourceElementRef ( ref , output , _) or
796
697
summaryElementRef ( ref , _, output , _)
797
698
) and
798
- len ( output , idx ) and
699
+ specLength ( output , idx ) and
799
700
node = TAst ( ref )
800
701
or
801
702
exists ( Top mid , string c , Node n |
@@ -827,7 +728,7 @@ private predicate interpretInput(string input, int idx, Top ref, TAstOrNode node
827
728
sinkElementRef ( ref , input , _) or
828
729
summaryElementRef ( ref , input , _, _)
829
730
) and
830
- len ( input , idx ) and
731
+ specLength ( input , idx ) and
831
732
node = TAst ( ref )
832
733
or
833
734
exists ( Top mid , string c , Node n |
0 commit comments