@@ -10,6 +10,7 @@ private import FlowSummaryImpl::Private
10
10
private import FlowSummaryImpl:: Public
11
11
private import semmle.code.java.dataflow.ExternalFlow
12
12
private import semmle.code.java.dataflow.FlowSummary as FlowSummary
13
+ private import semmle.code.java.dataflow.internal.AccessPathSyntax as AccessPathSyntax
13
14
14
15
class SummarizedCallableBase = FlowSummary:: SummarizedCallableBase ;
15
16
@@ -65,6 +66,66 @@ private boolean isGenerated(string provenance) {
65
66
provenance != "generated" and result = false
66
67
}
67
68
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
+
68
129
/**
69
130
* Holds if an external flow summary exists for `c` with input specification
70
131
* `input`, output specification `output`, kind `kind`, and a flag `generated`
@@ -75,11 +136,19 @@ predicate summaryElement(
75
136
) {
76
137
exists (
77
138
string namespace , string type , boolean subtypes , string name , string signature , string ext ,
78
- string provenance
139
+ string provenance , string originalInput , string originalOutput , Callable baseCallable
79
140
|
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
81
143
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
+ )
83
152
)
84
153
}
85
154
@@ -149,11 +218,16 @@ class SourceOrSinkElement = Top;
149
218
predicate sourceElement ( SourceOrSinkElement e , string output , string kind , boolean generated ) {
150
219
exists (
151
220
string namespace , string type , boolean subtypes , string name , string signature , string ext ,
152
- string provenance
221
+ string provenance , SourceOrSinkElement baseSource , string originalOutput
153
222
|
154
- sourceModel ( namespace , type , subtypes , name , signature , ext , output , kind , provenance ) and
223
+ sourceModel ( namespace , type , subtypes , name , signature , ext , originalOutput , kind , provenance ) and
155
224
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
+ )
157
231
)
158
232
}
159
233
@@ -165,11 +239,16 @@ predicate sourceElement(SourceOrSinkElement e, string output, string kind, boole
165
239
predicate sinkElement ( SourceOrSinkElement e , string input , string kind , boolean generated ) {
166
240
exists (
167
241
string namespace , string type , boolean subtypes , string name , string signature , string ext ,
168
- string provenance
242
+ string provenance , SourceOrSinkElement baseSink , string originalInput
169
243
|
170
- sinkModel ( namespace , type , subtypes , name , signature , ext , input , kind , provenance ) and
244
+ sinkModel ( namespace , type , subtypes , name , signature , ext , originalInput , kind , provenance ) and
171
245
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
+ )
173
252
)
174
253
}
175
254
0 commit comments