6767import java
6868private import semmle.code.java.dataflow.DataFlow:: DataFlow
6969private import internal.DataFlowPrivate
70+ private import internal.FlowSummaryImpl:: Private:: External
7071private import FlowSummary
7172
7273/**
@@ -498,10 +499,15 @@ module CsvValidation {
498499 or
499500 summaryModel ( _, _, _, _, _, _, input , _, _) and pred = "summary"
500501 |
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
505511 msg = "Unrecognized input specification \"" + part + "\" in " + pred + " model."
506512 )
507513 or
@@ -510,11 +516,9 @@ module CsvValidation {
510516 or
511517 summaryModel ( _, _, _, _, _, _, _, output , _) and pred = "summary"
512518 |
513- specSplit ( output , part , _ ) and
514- not part . regexpMatch ( "|ReturnValue|ArrayElement|Element|MapKey|MapValue" ) and
519+ invalidSpecComponent ( output , part ) and
520+ not part = "" and
515521 not ( part = [ "Argument" , "Parameter" ] and pred = "source" ) and
516- not parseArg ( part , _) and
517- not parseParam ( part , _) and
518522 msg = "Unrecognized output specification \"" + part + "\" in " + pred + " model."
519523 )
520524 or
@@ -624,7 +628,11 @@ private predicate sinkElement(Element e, string input, string kind) {
624628 )
625629}
626630
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 ) {
628636 exists (
629637 string namespace , string type , boolean subtypes , string name , string signature , string ext
630638 |
@@ -633,52 +641,14 @@ private predicate summaryElement(Element e, string input, string output, string
633641 )
634642}
635643
636- private string inOutSpec ( ) {
644+ /** Gets a specification used in a source model, sink model, or summary model. */
645+ string inOutSpec ( ) {
637646 sourceModel ( _, _, _, _, _, _, result , _) or
638647 sinkModel ( _, _, _, _, _, _, result , _) or
639648 summaryModel ( _, _, _, _, _, _, result , _, _) or
640649 summaryModel ( _, _, _, _, _, _, _, result , _)
641650}
642651
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-
682652private predicate inputNeedsReference ( string c ) {
683653 c = "Argument" or
684654 parseArg ( c , _)
@@ -693,7 +663,7 @@ private predicate outputNeedsReference(string c) {
693663private predicate sourceElementRef ( Top ref , string output , string kind ) {
694664 exists ( Element e |
695665 sourceElement ( e , output , kind ) and
696- if outputNeedsReference ( getLast ( output ) )
666+ if outputNeedsReference ( specLast ( output ) )
697667 then ref .( Call ) .getCallee ( ) .getSourceDeclaration ( ) = e
698668 else ref = e
699669 )
@@ -702,7 +672,7 @@ private predicate sourceElementRef(Top ref, string output, string kind) {
702672private predicate sinkElementRef ( Top ref , string input , string kind ) {
703673 exists ( Element e |
704674 sinkElement ( e , input , kind ) and
705- if inputNeedsReference ( getLast ( input ) )
675+ if inputNeedsReference ( specLast ( input ) )
706676 then ref .( Call ) .getCallee ( ) .getSourceDeclaration ( ) = e
707677 else ref = e
708678 )
@@ -711,81 +681,12 @@ private predicate sinkElementRef(Top ref, string input, string kind) {
711681private predicate summaryElementRef ( Top ref , string input , string output , string kind ) {
712682 exists ( Element e |
713683 summaryElement ( e , input , output , kind ) and
714- if inputNeedsReference ( getLast ( input ) )
684+ if inputNeedsReference ( specLast ( input ) )
715685 then ref .( Call ) .getCallee ( ) .getSourceDeclaration ( ) = e
716686 else ref = e
717687 )
718688}
719689
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-
789690private newtype TAstOrNode =
790691 TAst ( Top t ) or
791692 TNode ( Node n )
@@ -795,7 +696,7 @@ private predicate interpretOutput(string output, int idx, Top ref, TAstOrNode no
795696 sourceElementRef ( ref , output , _) or
796697 summaryElementRef ( ref , _, output , _)
797698 ) and
798- len ( output , idx ) and
699+ specLength ( output , idx ) and
799700 node = TAst ( ref )
800701 or
801702 exists ( Top mid , string c , Node n |
@@ -827,7 +728,7 @@ private predicate interpretInput(string input, int idx, Top ref, TAstOrNode node
827728 sinkElementRef ( ref , input , _) or
828729 summaryElementRef ( ref , input , _, _)
829730 ) and
830- len ( input , idx ) and
731+ specLength ( input , idx ) and
831732 node = TAst ( ref )
832733 or
833734 exists ( Top mid , string c , Node n |
0 commit comments