@@ -68,6 +68,7 @@ import java
6868private import semmle.code.java.dataflow.DataFlow:: DataFlow
6969private import internal.DataFlowPrivate
7070private import internal.FlowSummaryImpl:: Private:: External
71+ private import internal.FlowSummaryImplSpecific
7172private import FlowSummary
7273
7374/**
@@ -359,7 +360,8 @@ private predicate summaryModel(string row) {
359360 any ( SummaryModelCsv s ) .row ( row )
360361}
361362
362- private predicate sourceModel (
363+ /** Holds if a source model exists for the given parameters. */
364+ predicate sourceModel (
363365 string namespace , string type , boolean subtypes , string name , string signature , string ext ,
364366 string output , string kind
365367) {
@@ -377,7 +379,8 @@ private predicate sourceModel(
377379 )
378380}
379381
380- private predicate sinkModel (
382+ /** Holds if a sink model exists for the given parameters. */
383+ predicate sinkModel (
381384 string namespace , string type , boolean subtypes , string name , string signature , string ext ,
382385 string input , string kind
383386) {
@@ -395,7 +398,8 @@ private predicate sinkModel(
395398 )
396399}
397400
398- private predicate summaryModel (
401+ /** Holds if a summary model exists for the given parameters. */
402+ predicate summaryModel (
399403 string namespace , string type , boolean subtypes , string name , string signature , string ext ,
400404 string input , string output , string kind
401405) {
@@ -600,7 +604,8 @@ private Element interpretElement0(
600604 )
601605}
602606
603- private Element interpretElement (
607+ /** Gets the source/sink/summary element corresponding to the supplied parameters. */
608+ Element interpretElement (
604609 string namespace , string type , boolean subtypes , string name , string signature , string ext
605610) {
606611 elementSpec ( namespace , type , subtypes , name , signature , ext ) and
@@ -611,166 +616,25 @@ private Element interpretElement(
611616 )
612617}
613618
614- private predicate sourceElement ( Element e , string output , string kind ) {
615- exists (
616- string namespace , string type , boolean subtypes , string name , string signature , string ext
617- |
618- sourceModel ( namespace , type , subtypes , name , signature , ext , output , kind ) and
619- e = interpretElement ( namespace , type , subtypes , name , signature , ext )
620- )
621- }
622-
623- private predicate sinkElement ( Element e , string input , string kind ) {
624- exists (
625- string namespace , string type , boolean subtypes , string name , string signature , string ext
626- |
627- sinkModel ( namespace , type , subtypes , name , signature , ext , input , kind ) and
628- e = interpretElement ( namespace , type , subtypes , name , signature , ext )
629- )
630- }
631-
632- /**
633- * Holds if an external flow summary exists for `e` with input specification
634- * `input`, output specification `output`, and kind `kind`.
635- */
636- predicate summaryElement ( Element e , string input , string output , string kind ) {
637- exists (
638- string namespace , string type , boolean subtypes , string name , string signature , string ext
639- |
640- summaryModel ( namespace , type , subtypes , name , signature , ext , input , output , kind ) and
641- e = interpretElement ( namespace , type , subtypes , name , signature , ext )
642- )
643- }
644-
645- /** Gets a specification used in a source model, sink model, or summary model. */
646- string inOutSpec ( ) {
647- sourceModel ( _, _, _, _, _, _, result , _) or
648- sinkModel ( _, _, _, _, _, _, result , _) or
649- summaryModel ( _, _, _, _, _, _, result , _, _) or
650- summaryModel ( _, _, _, _, _, _, _, result , _)
651- }
652-
653- private predicate inputNeedsReference ( string c ) {
654- c = "Argument" or
655- parseArg ( c , _)
656- }
657-
658- private predicate outputNeedsReference ( string c ) {
659- c = "Argument" or
660- parseArg ( c , _) or
661- c = "ReturnValue"
662- }
663-
664- private predicate sourceElementRef ( Top ref , string output , string kind ) {
665- exists ( Element e |
666- sourceElement ( e , output , kind ) and
667- if outputNeedsReference ( specLast ( output ) )
668- then ref .( Call ) .getCallee ( ) .getSourceDeclaration ( ) = e
669- else ref = e
670- )
671- }
672-
673- private predicate sinkElementRef ( Top ref , string input , string kind ) {
674- exists ( Element e |
675- sinkElement ( e , input , kind ) and
676- if inputNeedsReference ( specLast ( input ) )
677- then ref .( Call ) .getCallee ( ) .getSourceDeclaration ( ) = e
678- else ref = e
679- )
680- }
681-
682- private predicate summaryElementRef ( Top ref , string input , string output , string kind ) {
683- exists ( Element e |
684- summaryElement ( e , input , output , kind ) and
685- if inputNeedsReference ( specLast ( input ) )
686- then ref .( Call ) .getCallee ( ) .getSourceDeclaration ( ) = e
687- else ref = e
688- )
689- }
690-
691- private newtype TAstOrNode =
692- TAst ( Top t ) or
693- TNode ( Node n )
694-
695- private predicate interpretOutput ( string output , int idx , Top ref , TAstOrNode node ) {
696- (
697- sourceElementRef ( ref , output , _) or
698- summaryElementRef ( ref , _, output , _)
699- ) and
700- specLength ( output , idx ) and
701- node = TAst ( ref )
702- or
703- exists ( Top mid , string c , Node n |
704- interpretOutput ( output , idx + 1 , ref , TAst ( mid ) ) and
705- specSplit ( output , c , idx ) and
706- node = TNode ( n )
707- |
708- exists ( int pos | n .( PostUpdateNode ) .getPreUpdateNode ( ) .( ArgumentNode ) .argumentOf ( mid , pos ) |
709- c = "Argument" or parseArg ( c , pos )
710- )
711- or
712- exists ( int pos | n .( ParameterNode ) .isParameterOf ( mid , pos ) |
713- c = "Parameter" or parseParam ( c , pos )
714- )
715- or
716- ( c = "Parameter" or c = "" ) and
717- n .asParameter ( ) = mid
718- or
719- c = "ReturnValue" and
720- n .asExpr ( ) .( Call ) = mid
721- or
722- c = "" and
723- n .asExpr ( ) .( FieldRead ) .getField ( ) = mid
724- )
725- }
726-
727- private predicate interpretInput ( string input , int idx , Top ref , TAstOrNode node ) {
728- (
729- sinkElementRef ( ref , input , _) or
730- summaryElementRef ( ref , input , _, _)
731- ) and
732- specLength ( input , idx ) and
733- node = TAst ( ref )
734- or
735- exists ( Top mid , string c , Node n |
736- interpretInput ( input , idx + 1 , ref , TAst ( mid ) ) and
737- specSplit ( input , c , idx ) and
738- node = TNode ( n )
739- |
740- exists ( int pos | n .( ArgumentNode ) .argumentOf ( mid , pos ) | c = "Argument" or parseArg ( c , pos ) )
741- or
742- exists ( ReturnStmt ret |
743- c = "ReturnValue" and
744- n .asExpr ( ) = ret .getResult ( ) and
745- mid = ret .getEnclosingCallable ( )
746- )
747- or
748- exists ( FieldWrite fw |
749- c = "" and
750- fw .getField ( ) = mid and
751- n .asExpr ( ) = fw .getRHS ( )
752- )
753- )
754- }
619+ cached
620+ private module Cached {
621+ /**
622+ * Holds if `node` is specified as a source with the given kind in a CSV flow
623+ * model.
624+ */
625+ cached
626+ predicate sourceNode ( Node node , string kind ) {
627+ exists ( InterpretNode n | isSourceNode ( n , kind ) and n .asNode ( ) = node )
628+ }
755629
756- /**
757- * Holds if `node` is specified as a source with the given kind in a CSV flow
758- * model.
759- */
760- predicate sourceNode ( Node node , string kind ) {
761- exists ( Top ref , string output |
762- sourceElementRef ( ref , output , kind ) and
763- interpretOutput ( output , 0 , ref , TNode ( node ) )
764- )
630+ /**
631+ * Holds if `node` is specified as a sink with the given kind in a CSV flow
632+ * model.
633+ */
634+ cached
635+ predicate sinkNode ( Node node , string kind ) {
636+ exists ( InterpretNode n | isSinkNode ( n , kind ) and n .asNode ( ) = node )
637+ }
765638}
766639
767- /**
768- * Holds if `node` is specified as a sink with the given kind in a CSV flow
769- * model.
770- */
771- predicate sinkNode ( Node node , string kind ) {
772- exists ( Top ref , string input |
773- sinkElementRef ( ref , input , kind ) and
774- interpretInput ( input , 0 , ref , TNode ( node ) )
775- )
776- }
640+ import Cached
0 commit comments