@@ -144,7 +144,13 @@ module LodashUnderscore {
144
144
name = [ "union" , "zip" ] and
145
145
pred = call .getAnArgument ( ) and
146
146
succ = call
147
- or
147
+ )
148
+ }
149
+
150
+ private predicate underscoreTaintStepLegacy ( DataFlow:: Node pred , DataFlow:: Node succ ) {
151
+ exists ( string name , DataFlow:: CallNode call |
152
+ call = any ( Member member | member .getName ( ) = name ) .getACall ( )
153
+ |
148
154
name =
149
155
[ "each" , "map" , "every" , "some" , "max" , "min" , "sortBy" , "partition" , "mapObject" , "tap" ] and
150
156
pred = call .getArgument ( 0 ) and
@@ -168,6 +174,169 @@ module LodashUnderscore {
168
174
underscoreTaintStep ( pred , succ )
169
175
}
170
176
}
177
+
178
+ private class UnderscoreTaintStepLegacy extends TaintTracking:: LegacyTaintStep {
179
+ override predicate step ( DataFlow:: Node pred , DataFlow:: Node succ ) {
180
+ underscoreTaintStepLegacy ( pred , succ )
181
+ }
182
+ }
183
+
184
+ private class LodashEach extends DataFlow:: SummarizedCallable {
185
+ LodashEach ( ) { this = "_.each-like" }
186
+
187
+ override DataFlow:: CallNode getACall ( ) {
188
+ result = member ( [ "each" , "eachRight" , "forEach" , "forEachRight" , "every" , "some" ] ) .getACall ( )
189
+ }
190
+
191
+ override predicate propagatesFlow ( string input , string output , boolean preservesValue ) {
192
+ preservesValue = true and
193
+ input = "Argument[0].ArrayElement" and
194
+ output = "Argument[1].Parameter[0]"
195
+ }
196
+ }
197
+
198
+ private class LodashMap extends DataFlow:: SummarizedCallable {
199
+ LodashMap ( ) { this = "_.map" }
200
+
201
+ override DataFlow:: CallNode getACall ( ) { result = member ( "map" ) .getACall ( ) }
202
+
203
+ override predicate propagatesFlow ( string input , string output , boolean preservesValue ) {
204
+ (
205
+ input = "Argument[0].ArrayElement" and
206
+ output = "Argument[1].Parameter[0]"
207
+ or
208
+ input = "Argument[1].ReturnValue" and
209
+ output = "ReturnValue.ArrayElement"
210
+ ) and
211
+ preservesValue = true
212
+ }
213
+ }
214
+
215
+ private class LodashFlatMap extends DataFlow:: SummarizedCallable {
216
+ LodashFlatMap ( ) { this = "_.flatMap" }
217
+
218
+ override DataFlow:: CallNode getACall ( ) { result = member ( "flatMap" ) .getACall ( ) }
219
+
220
+ override predicate propagatesFlow ( string input , string output , boolean preservesValue ) {
221
+ (
222
+ input = "Argument[0].ArrayElement" and
223
+ output = "Argument[1].Parameter[0]"
224
+ or
225
+ input = "Argument[1].ReturnValue.WithoutArrayElement" and
226
+ output = "ReturnValue.ArrayElement"
227
+ or
228
+ input = "Argument[1].ReturnValue.ArrayElement" and
229
+ output = "ReturnValue.ArrayElement"
230
+ ) and
231
+ preservesValue = true
232
+ }
233
+ }
234
+
235
+ private class LodashFlatMapDeep extends DataFlow:: SummarizedCallable {
236
+ LodashFlatMapDeep ( ) { this = "_.flatMapDeep" }
237
+
238
+ override DataFlow:: CallNode getACall ( ) {
239
+ result = member ( [ "flatMapDeep" , "flatMapDepth" ] ) .getACall ( )
240
+ }
241
+
242
+ override predicate propagatesFlow ( string input , string output , boolean preservesValue ) {
243
+ (
244
+ input = "Argument[0].ArrayElement" and
245
+ output = "Argument[1].Parameter[0]"
246
+ or
247
+ input = "Argument[1].ReturnValue.WithoutArrayElement" and
248
+ output = "ReturnValue.ArrayElement"
249
+ or
250
+ input = "Argument[1].ReturnValue.ArrayElementDeep" and
251
+ output = "ReturnValue.ArrayElement"
252
+ ) and
253
+ preservesValue = true
254
+ }
255
+ }
256
+
257
+ private class LodashReduce extends DataFlow:: SummarizedCallable {
258
+ LodashReduce ( ) { this = "_.reduce-like" }
259
+
260
+ override DataFlow:: CallNode getACall ( ) { result = member ( [ "reduce" , "reduceRight" ] ) .getACall ( ) }
261
+
262
+ override predicate propagatesFlow ( string input , string output , boolean preservesValue ) {
263
+ (
264
+ input = "Argument[0].ArrayElement" and
265
+ output = "Argument[1].Parameter[1]"
266
+ or
267
+ input = [ "Argument[1].ReturnValue" , "Argument[2]" ] and
268
+ output = [ "ReturnValue" , "Argument[1].Parameter[0]" ]
269
+ ) and
270
+ preservesValue = true
271
+ }
272
+ }
273
+
274
+ private class LoashSortBy extends DataFlow:: SummarizedCallable {
275
+ LoashSortBy ( ) { this = "_.sortBy-like" }
276
+
277
+ override DataFlow:: CallNode getACall ( ) { result = member ( [ "sortBy" , "orderBy" ] ) .getACall ( ) }
278
+
279
+ override predicate propagatesFlow ( string input , string output , boolean preservesValue ) {
280
+ input = "Argument[0].ArrayElement" and
281
+ output = [ "Argument[1].Parameter[1]" , "ReturnValue.ArrayElement" ] and
282
+ preservesValue = true
283
+ }
284
+ }
285
+
286
+ private class LodashMinMaxBy extends DataFlow:: SummarizedCallable {
287
+ LodashMinMaxBy ( ) { this = "_.minBy / _.maxBy" }
288
+
289
+ override DataFlow:: CallNode getACall ( ) { result = member ( [ "minBy" , "maxBy" ] ) .getACall ( ) }
290
+
291
+ override predicate propagatesFlow ( string input , string output , boolean preservesValue ) {
292
+ input = "Argument[0].ArrayElement" and
293
+ output = [ "Argument[1].Parameter[1]" , "ReturnValue" ] and
294
+ preservesValue = true
295
+ }
296
+ }
297
+
298
+ private class LodashPartition extends DataFlow:: SummarizedCallable {
299
+ LodashPartition ( ) { this = "_.partition" }
300
+
301
+ override DataFlow:: CallNode getACall ( ) { result = member ( [ "partition" ] ) .getACall ( ) }
302
+
303
+ override predicate propagatesFlow ( string input , string output , boolean preservesValue ) {
304
+ input = "Argument[0].ArrayElement" and
305
+ output = [ "Argument[1].Parameter[1]" , "ReturnValue.ArrayElement.ArrayElement" ] and
306
+ preservesValue = true
307
+ }
308
+ }
309
+
310
+ private class UnderscoreMapObject extends DataFlow:: SummarizedCallable {
311
+ UnderscoreMapObject ( ) { this = "_.mapObject" }
312
+
313
+ override DataFlow:: CallNode getACall ( ) { result = member ( "mapObject" ) .getACall ( ) }
314
+
315
+ override predicate propagatesFlow ( string input , string output , boolean preservesValue ) {
316
+ // Just collapse all properties with AnyMember. We could be more precise by generating a summary
317
+ // for each property name, but for a rarely-used method like this it dosn't seem worth it.
318
+ (
319
+ input = "Argument[0].AnyMember" and
320
+ output = "Argument[1].Parameter[1]"
321
+ or
322
+ input = "Argument[1].ReturnValue" and
323
+ output = "ReturnValue.AnyMember"
324
+ ) and
325
+ preservesValue = true
326
+ }
327
+ }
328
+
329
+ private class LodashTap extends DataFlow:: SummarizedCallable {
330
+ LodashTap ( ) { this = "_.tap" }
331
+
332
+ override DataFlow:: CallNode getACall ( ) { result = member ( "tap" ) .getACall ( ) }
333
+
334
+ override predicate propagatesFlow ( string input , string output , boolean preservesValue ) {
335
+ input = "Argument[0]" and
336
+ output = [ "Argument[1].Parameter[0]" , "ReturnValue" ] and
337
+ preservesValue = true
338
+ }
339
+ }
171
340
}
172
341
173
342
/**
0 commit comments