@@ -305,7 +305,143 @@ module ActiveSupport {
305
305
preservesValue = true
306
306
}
307
307
}
308
- // TODO: index_with, pick, pluck (they require Hash dataflow)
308
+
309
+ private class IndexWithSummary extends SimpleSummarizedCallable {
310
+ IndexWithSummary ( ) { this = "index_with" }
311
+
312
+ override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
313
+ input = "Argument[self].Element[any]" and
314
+ output = "Argument[block].Parameter[0]" and
315
+ preservesValue = true
316
+ or
317
+ input = [ "Argument[0]" , "Argument[block].ReturnValue" ] and
318
+ output = "ReturnValue.Element[?]" and
319
+ preservesValue = true
320
+ }
321
+ }
322
+
323
+ private string getKeyArgument ( MethodCall mc , int i ) {
324
+ mc .getMethodName ( ) = [ "pick" , "pluck" ] and
325
+ result = DataFlow:: Content:: getKnownElementIndex ( mc .getArgument ( i ) ) .serialize ( )
326
+ }
327
+
328
+ private class PickSingleSummary extends SummarizedCallable {
329
+ private MethodCall mc ;
330
+ private string key ;
331
+
332
+ PickSingleSummary ( ) {
333
+ key = getKeyArgument ( mc , 0 ) and
334
+ this = "Enumerable.pick(" + key + ")" and
335
+ mc .getMethodName ( ) = "pick" and
336
+ mc .getNumberOfArguments ( ) = 1
337
+ }
338
+
339
+ override MethodCall getACall ( ) { result = mc }
340
+
341
+ override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
342
+ input = "Argument[self].Element[0].Element[" + key + "]" and
343
+ output = "ReturnValue" and
344
+ preservesValue = true
345
+ }
346
+ }
347
+
348
+ private class PickMultipleSummary extends SummarizedCallable {
349
+ private MethodCall mc ;
350
+
351
+ PickMultipleSummary ( ) {
352
+ mc .getMethodName ( ) = "pick" and
353
+ mc .getNumberOfArguments ( ) > 1 and
354
+ exists ( int maxKey |
355
+ maxKey = max ( int j | exists ( getKeyArgument ( mc , j ) ) ) and
356
+ this =
357
+ "Enumerable.pick(" +
358
+ concat ( int i , string key |
359
+ key = getKeyArgument ( mc , i )
360
+ or
361
+ key = "_" and
362
+ not exists ( getKeyArgument ( mc , i ) ) and
363
+ i in [ 0 .. maxKey ]
364
+ |
365
+ key , "," order by i
366
+ ) + ")"
367
+ )
368
+ }
369
+
370
+ override MethodCall getACall ( ) { result = mc }
371
+
372
+ override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
373
+ exists ( string s , int i |
374
+ s = getKeyArgument ( mc , i ) and
375
+ input = "Argument[self].Element[0].Element[" + s + "]" and
376
+ output = "ReturnValue.Element[" + i + "]"
377
+ ) and
378
+ preservesValue = true
379
+ }
380
+ }
381
+
382
+ private class PluckSingleSummary extends SummarizedCallable {
383
+ private MethodCall mc ;
384
+ private string key ;
385
+
386
+ PluckSingleSummary ( ) {
387
+ key = getKeyArgument ( mc , 0 ) and
388
+ this = "Enumerable.pluck(" + key + ")" and
389
+ mc .getMethodName ( ) = "pluck" and
390
+ mc .getNumberOfArguments ( ) = 1
391
+ }
392
+
393
+ override MethodCall getACall ( ) { result = mc }
394
+
395
+ override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
396
+ input = "Argument[self].Element[any].Element[" + key + "]" and
397
+ output = "ReturnValue.Element[any]" and
398
+ preservesValue = true
399
+ }
400
+ }
401
+
402
+ private class PluckMultipleSummary extends SummarizedCallable {
403
+ private MethodCall mc ;
404
+
405
+ PluckMultipleSummary ( ) {
406
+ mc .getMethodName ( ) = "pluck" and
407
+ mc .getNumberOfArguments ( ) > 1 and
408
+ exists ( int maxKey |
409
+ maxKey = max ( int j | exists ( getKeyArgument ( mc , j ) ) ) and
410
+ this =
411
+ "Enumerable.pluck(" +
412
+ concat ( int i , string key |
413
+ key = getKeyArgument ( mc , i )
414
+ or
415
+ key = "_" and
416
+ not exists ( getKeyArgument ( mc , i ) ) and
417
+ i in [ 0 .. maxKey ]
418
+ |
419
+ key , "," order by i
420
+ ) + ")"
421
+ )
422
+ }
423
+
424
+ override MethodCall getACall ( ) { result = mc }
425
+
426
+ override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
427
+ exists ( string s , int i |
428
+ s = getKeyArgument ( mc , i ) and
429
+ input = "Argument[self].Element[any].Element[" + s + "]" and
430
+ output = "ReturnValue.Element[?].Element[" + i + "]"
431
+ ) and
432
+ preservesValue = true
433
+ }
434
+ }
435
+
436
+ private class SoleSummary extends SimpleSummarizedCallable {
437
+ SoleSummary ( ) { this = "sole" }
438
+
439
+ override predicate propagatesFlowExt ( string input , string output , boolean preservesValue ) {
440
+ input = "Argument[self].Element[0]" and
441
+ output = "ReturnValue" and
442
+ preservesValue = true
443
+ }
444
+ }
309
445
}
310
446
}
311
447
0 commit comments