6767import java
6868private import semmle.code.java.dataflow.DataFlow:: DataFlow
6969private import internal.DataFlowPrivate
70+ private import FlowSummary
7071
7172/**
7273 * A module importing the frameworks that provide external flow data,
@@ -459,7 +460,8 @@ module CsvValidation {
459460 summaryModel ( _, _, _, _, _, _, input , _, _) and pred = "summary"
460461 |
461462 specSplit ( input , part , _) and
462- not part .regexpMatch ( "|Argument|ReturnValue" ) and
463+ not part .regexpMatch ( "|ReturnValue|ArrayElement|Element|MapKey|MapValue" ) and
464+ not ( part = "Argument" and pred = "sink" ) and
463465 not parseArg ( part , _) and
464466 msg = "Unrecognized input specification \"" + part + "\" in " + pred + " model."
465467 )
@@ -470,7 +472,8 @@ module CsvValidation {
470472 summaryModel ( _, _, _, _, _, _, _, output , _) and pred = "summary"
471473 |
472474 specSplit ( output , part , _) and
473- not part .regexpMatch ( "|Argument|Parameter|ReturnValue" ) and
475+ not part .regexpMatch ( "|ReturnValue|ArrayElement|Element|MapKey|MapValue" ) and
476+ not ( part = [ "Argument" , "Parameter" ] and pred = "source" ) and
474477 not parseArg ( part , _) and
475478 not parseParam ( part , _) and
476479 msg = "Unrecognized output specification \"" + part + "\" in " + pred + " model."
@@ -675,6 +678,75 @@ private predicate summaryElementRef(Top ref, string input, string output, string
675678 )
676679}
677680
681+ private SummaryComponent interpretComponent ( string c ) {
682+ specSplit ( _, c , _) and
683+ (
684+ exists ( int pos | parseArg ( c , pos ) and result = SummaryComponent:: argument ( pos ) )
685+ or
686+ exists ( int pos | parseParam ( c , pos ) and result = SummaryComponent:: parameter ( pos ) )
687+ or
688+ c = "ReturnValue" and result = SummaryComponent:: return ( )
689+ or
690+ c = "ArrayElement" and result = SummaryComponent:: content ( any ( ArrayContent c0 ) )
691+ or
692+ c = "Element" and result = SummaryComponent:: content ( any ( CollectionContent c0 ) )
693+ or
694+ c = "MapKey" and result = SummaryComponent:: content ( any ( MapKeyContent c0 ) )
695+ or
696+ c = "MapValue" and result = SummaryComponent:: content ( any ( MapValueContent c0 ) )
697+ )
698+ }
699+
700+ private predicate interpretSpec ( string spec , int idx , SummaryComponentStack stack ) {
701+ exists ( string c |
702+ summaryElement ( _, spec , _, _) or
703+ summaryElement ( _, _, spec , _)
704+ |
705+ len ( spec , idx + 1 ) and
706+ specSplit ( spec , c , idx ) and
707+ stack = SummaryComponentStack:: singleton ( interpretComponent ( c ) )
708+ )
709+ or
710+ exists ( SummaryComponent head , SummaryComponentStack tail |
711+ interpretSpec ( spec , idx , head , tail ) and
712+ stack = SummaryComponentStack:: push ( head , tail )
713+ )
714+ }
715+
716+ private predicate interpretSpec (
717+ string output , int idx , SummaryComponent head , SummaryComponentStack tail
718+ ) {
719+ exists ( string c |
720+ interpretSpec ( output , idx + 1 , tail ) and
721+ specSplit ( output , c , idx ) and
722+ head = interpretComponent ( c )
723+ )
724+ }
725+
726+ private class MkStack extends RequiredSummaryComponentStack {
727+ MkStack ( ) { interpretSpec ( _, _, _, this ) }
728+
729+ override predicate required ( SummaryComponent c ) { interpretSpec ( _, _, c , this ) }
730+ }
731+
732+ private class SummarizedCallableExternal extends SummarizedCallable {
733+ SummarizedCallableExternal ( ) { summaryElement ( this , _, _, _) }
734+
735+ override predicate propagatesFlow (
736+ SummaryComponentStack input , SummaryComponentStack output , boolean preservesValue
737+ ) {
738+ exists ( string inSpec , string outSpec , string kind |
739+ summaryElement ( this , inSpec , outSpec , kind ) and
740+ interpretSpec ( inSpec , 0 , input ) and
741+ interpretSpec ( outSpec , 0 , output )
742+ |
743+ kind = "value" and preservesValue = true
744+ or
745+ kind = "taint" and preservesValue = false
746+ )
747+ }
748+ }
749+
678750private newtype TAstOrNode =
679751 TAst ( Top t ) or
680752 TNode ( Node n )
@@ -761,15 +833,3 @@ predicate sinkNode(Node node, string kind) {
761833 interpretInput ( input , 0 , ref , TNode ( node ) )
762834 )
763835}
764-
765- /**
766- * Holds if `node1` to `node2` is specified as a flow step with the given kind
767- * in a CSV flow model.
768- */
769- predicate summaryStep ( Node node1 , Node node2 , string kind ) {
770- exists ( Top ref , string input , string output |
771- summaryElementRef ( ref , input , output , kind ) and
772- interpretInput ( input , 0 , ref , TNode ( node1 ) ) and
773- interpretOutput ( output , 0 , ref , TNode ( node2 ) )
774- )
775- }
0 commit comments