@@ -10,6 +10,7 @@ private import FlowSummaryImpl::Private
1010private import FlowSummaryImpl:: Public
1111private import semmle.code.java.dataflow.ExternalFlow
1212private import semmle.code.java.dataflow.FlowSummary as FlowSummary
13+ private import semmle.code.java.dataflow.internal.AccessPathSyntax as AccessPathSyntax
1314
1415class SummarizedCallableBase = FlowSummary:: SummarizedCallableBase ;
1516
@@ -65,6 +66,66 @@ private boolean isGenerated(string provenance) {
6566 provenance != "generated" and result = false
6667}
6768
69+ private predicate relatedArgSpec ( Callable c , string spec ) {
70+ exists (
71+ string namespace , string type , boolean subtypes , string name , string signature , string ext
72+ |
73+ summaryModel ( namespace , type , subtypes , name , signature , ext , spec , _, _, _) or
74+ summaryModel ( namespace , type , subtypes , name , signature , ext , _, spec , _, _) or
75+ sourceModel ( namespace , type , subtypes , name , signature , ext , spec , _, _) or
76+ sinkModel ( namespace , type , subtypes , name , signature , ext , spec , _, _)
77+ |
78+ c = interpretElement ( namespace , type , subtypes , name , signature , ext )
79+ )
80+ }
81+
82+ /**
83+ * Holds if `defaultsCallable` is a Kotlin default-parameter proxy for `originalCallable`, and
84+ * `originalCallable` has a model, and `defaultsArgSpec` is `originalArgSpec` adjusted to account
85+ * for the additional dispatch receiver parameter that occurs in the default-parameter proxy's argument
86+ * list. When no adjustment is required (e.g. for constructors, or non-argument-based specs), `defaultArgsSpec`
87+ * equals `originalArgSpec`.
88+ *
89+ * Note in the case where `originalArgSpec` uses an integer range, like `Argument[1..3]...`, this will produce multiple
90+ * results for `defaultsArgSpec`, like `{Argument[2]..., Argument[3]..., Argument[4]...}`.
91+ */
92+ private predicate correspondingKotlinParameterDefaultsArgSpec (
93+ Callable originalCallable , Callable defaultsCallable , string originalArgSpec ,
94+ string defaultsArgSpec
95+ ) {
96+ relatedArgSpec ( originalCallable , originalArgSpec ) and
97+ defaultsCallable = originalCallable .getKotlinParameterDefaultsProxy ( ) and
98+ (
99+ originalCallable instanceof Constructor and originalArgSpec = defaultsArgSpec
100+ or
101+ originalCallable instanceof Method and
102+ exists ( string regex |
103+ // Note I use a regex and not AccessPathToken because this feeds summaryElement et al,
104+ // which would introduce mutual recursion with the definition of AccessPathToken.
105+ regex = "Argument\\[([0-9,\\. ]+)\\](.*)" and
106+ (
107+ exists ( string oldArgNumber , string rest , int paramOffset |
108+ oldArgNumber = originalArgSpec .regexpCapture ( regex , 1 ) and
109+ rest = originalArgSpec .regexpCapture ( regex , 2 ) and
110+ paramOffset =
111+ defaultsCallable .getNumberOfParameters ( ) -
112+ ( originalCallable .getNumberOfParameters ( ) + 2 ) and
113+ exists ( int oldArgParsed |
114+ oldArgParsed = AccessPathSyntax:: AccessPath:: parseInt ( oldArgNumber .splitAt ( "," ) .trim ( ) )
115+ |
116+ if ktExtensionFunctions ( originalCallable , _, _) and oldArgParsed = 0
117+ then defaultsArgSpec = "Argument[0]"
118+ else defaultsArgSpec = "Argument[" + ( oldArgParsed + paramOffset ) + "]" + rest
119+ )
120+ )
121+ or
122+ not originalArgSpec .regexpMatch ( regex ) and
123+ defaultsArgSpec = originalArgSpec
124+ )
125+ )
126+ )
127+ }
128+
68129/**
69130 * Holds if an external flow summary exists for `c` with input specification
70131 * `input`, output specification `output`, kind `kind`, and a flag `generated`
@@ -75,11 +136,19 @@ predicate summaryElement(
75136) {
76137 exists (
77138 string namespace , string type , boolean subtypes , string name , string signature , string ext ,
78- string provenance
139+ string provenance , string originalInput , string originalOutput , Callable baseCallable
79140 |
80- summaryModel ( namespace , type , subtypes , name , signature , ext , input , output , kind , provenance ) and
141+ summaryModel ( namespace , type , subtypes , name , signature , ext , originalInput , originalOutput ,
142+ kind , provenance ) and
81143 generated = isGenerated ( provenance ) and
82- c .asCallable ( ) = interpretElement ( namespace , type , subtypes , name , signature , ext )
144+ baseCallable = interpretElement ( namespace , type , subtypes , name , signature , ext ) and
145+ (
146+ c .asCallable ( ) = baseCallable and input = originalInput and output = originalOutput
147+ or
148+ correspondingKotlinParameterDefaultsArgSpec ( baseCallable , c .asCallable ( ) , originalInput , input ) and
149+ correspondingKotlinParameterDefaultsArgSpec ( baseCallable , c .asCallable ( ) , originalOutput ,
150+ output )
151+ )
83152 )
84153}
85154
@@ -149,11 +218,16 @@ class SourceOrSinkElement = Top;
149218predicate sourceElement ( SourceOrSinkElement e , string output , string kind , boolean generated ) {
150219 exists (
151220 string namespace , string type , boolean subtypes , string name , string signature , string ext ,
152- string provenance
221+ string provenance , SourceOrSinkElement baseSource , string originalOutput
153222 |
154- sourceModel ( namespace , type , subtypes , name , signature , ext , output , kind , provenance ) and
223+ sourceModel ( namespace , type , subtypes , name , signature , ext , originalOutput , kind , provenance ) and
155224 generated = isGenerated ( provenance ) and
156- e = interpretElement ( namespace , type , subtypes , name , signature , ext )
225+ baseSource = interpretElement ( namespace , type , subtypes , name , signature , ext ) and
226+ (
227+ e = baseSource and output = originalOutput
228+ or
229+ correspondingKotlinParameterDefaultsArgSpec ( baseSource , e , originalOutput , output )
230+ )
157231 )
158232}
159233
@@ -165,11 +239,16 @@ predicate sourceElement(SourceOrSinkElement e, string output, string kind, boole
165239predicate sinkElement ( SourceOrSinkElement e , string input , string kind , boolean generated ) {
166240 exists (
167241 string namespace , string type , boolean subtypes , string name , string signature , string ext ,
168- string provenance
242+ string provenance , SourceOrSinkElement baseSink , string originalInput
169243 |
170- sinkModel ( namespace , type , subtypes , name , signature , ext , input , kind , provenance ) and
244+ sinkModel ( namespace , type , subtypes , name , signature , ext , originalInput , kind , provenance ) and
171245 generated = isGenerated ( provenance ) and
172- e = interpretElement ( namespace , type , subtypes , name , signature , ext )
246+ baseSink = interpretElement ( namespace , type , subtypes , name , signature , ext ) and
247+ (
248+ e = baseSink and originalInput = input
249+ or
250+ correspondingKotlinParameterDefaultsArgSpec ( baseSink , e , originalInput , input )
251+ )
173252 )
174253}
175254
0 commit comments