@@ -10,7 +10,6 @@ private import codeql.ruby.dataflow.internal.SsaImpl as SsaImpl
10
10
private import codeql.ruby.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
11
11
private import codeql.ruby.dataflow.internal.FlowSummaryImplSpecific as FlowSummaryImplSpecific
12
12
private import codeql.ruby.dataflow.internal.AccessPathSyntax
13
- private import codeql.ruby.frameworks.core.Hash
14
13
15
14
class Node = DataFlowPublic:: Node ;
16
15
@@ -60,6 +59,15 @@ class ContentFilter extends TContentFilter {
60
59
}
61
60
}
62
61
62
+ /** Module for getting `ContentFilter` values. */
63
+ module ContentFilter {
64
+ /** Gets the filter that only allow element contents. */
65
+ ContentFilter hasElements ( ) { result = MkElementFilter ( ) }
66
+
67
+ /** Gets the filter that only allow pair-value contents. */
68
+ ContentFilter hasPairValue ( ) { result = MkPairValueFilter ( ) }
69
+ }
70
+
63
71
/**
64
72
* Holds if a value stored with `storeContents` can be read back with `loadContents`.
65
73
*/
@@ -225,28 +233,9 @@ predicate basicStoreStep(Node nodeFrom, Node nodeTo, DataFlow::ContentSet conten
225
233
nodeTo = evaluateSummaryComponentStackLocal ( callable , call , output )
226
234
)
227
235
or
228
- // Hash literals
229
- exists ( Cfg:: CfgNodes:: ExprNodes:: PairCfgNode pair |
230
- hashLiteralStore ( nodeTo , any ( DataFlow:: Node n | n .asExpr ( ) = pair ) ) and
231
- nodeFrom .asExpr ( ) = pair .getValue ( )
232
- |
233
- exists ( ConstantValue constant |
234
- constant = pair .getKey ( ) .getConstantValue ( ) and
235
- contents .isSingleton ( DataFlow:: Content:: getElementContent ( constant ) )
236
- )
237
- or
238
- not exists ( pair .getKey ( ) .getConstantValue ( ) ) and
239
- contents .isAnyElement ( )
240
- )
241
- or
242
236
TypeTrackingStep:: storeStep ( nodeFrom , nodeTo , contents )
243
237
}
244
238
245
- private predicate hashLiteralStore ( DataFlow:: CallNode hashCreation , DataFlow:: Node argument ) {
246
- hashCreation .getExprNode ( ) .getExpr ( ) = Hash:: getAStaticHashCall ( "[]" ) and
247
- argument = hashCreation .getArgument ( _)
248
- }
249
-
250
239
/**
251
240
* Holds if a store step `nodeFrom -> nodeTo` with `contents` exists, where the destination node
252
241
* is a post-update node that should be treated as a local source node.
@@ -336,14 +325,6 @@ predicate basicWithContentStep(Node nodeFrom, Node nodeTo, ContentFilter filter)
336
325
nodeTo = evaluateSummaryComponentStackLocal ( callable , call , output )
337
326
)
338
327
or
339
- // Hash-splat in a hash literal
340
- exists ( DataFlow:: Node node |
341
- hashLiteralStore ( nodeTo , node ) and
342
- node .asExpr ( ) .getExpr ( ) instanceof HashSplatExpr and
343
- nodeFrom .asExpr ( ) = node .asExpr ( ) .( Cfg:: CfgNodes:: ExprNodes:: UnaryOperationCfgNode ) .getOperand ( ) and
344
- filter = MkElementFilter ( )
345
- )
346
- or
347
328
TypeTrackingStep:: withContentStep ( nodeFrom , nodeTo , filter )
348
329
}
349
330
@@ -361,6 +342,7 @@ private predicate hasStoreSummary(
361
342
SummarizedCallable callable , DataFlow:: ContentSet contents , SummaryComponentStack input ,
362
343
SummaryComponentStack output
363
344
) {
345
+ not TypeTrackingStep:: suppressSummary ( callable ) and
364
346
callable .propagatesFlow ( input , push ( SummaryComponent:: content ( contents ) , output ) , true ) and
365
347
not isNonLocal ( input .head ( ) ) and
366
348
not isNonLocal ( output .head ( ) )
@@ -371,6 +353,7 @@ private predicate hasLoadSummary(
371
353
SummarizedCallable callable , DataFlow:: ContentSet contents , SummaryComponentStack input ,
372
354
SummaryComponentStack output
373
355
) {
356
+ not TypeTrackingStep:: suppressSummary ( callable ) and
374
357
callable .propagatesFlow ( push ( SummaryComponent:: content ( contents ) , input ) , output , true ) and
375
358
not isNonLocal ( input .head ( ) ) and
376
359
not isNonLocal ( output .head ( ) )
@@ -381,12 +364,12 @@ private predicate hasLoadStoreSummary(
381
364
SummarizedCallable callable , DataFlow:: ContentSet loadContents ,
382
365
DataFlow:: ContentSet storeContents , SummaryComponentStack input , SummaryComponentStack output
383
366
) {
367
+ not TypeTrackingStep:: suppressSummary ( callable ) and
384
368
callable
385
369
.propagatesFlow ( push ( SummaryComponent:: content ( loadContents ) , input ) ,
386
370
push ( SummaryComponent:: content ( storeContents ) , output ) , true ) and
387
371
not isNonLocal ( input .head ( ) ) and
388
- not isNonLocal ( output .head ( ) ) and
389
- callable != "Hash.[]" // Special-cased due to having a huge number of summaries
372
+ not isNonLocal ( output .head ( ) )
390
373
}
391
374
392
375
/**
@@ -419,6 +402,7 @@ private predicate hasWithoutContentSummary(
419
402
SummaryComponentStack output
420
403
) {
421
404
exists ( DataFlow:: ContentSet content |
405
+ not TypeTrackingStep:: suppressSummary ( callable ) and
422
406
callable .propagatesFlow ( push ( SummaryComponent:: withoutContent ( content ) , input ) , output , true ) and
423
407
filter = getFilterFromWithoutContentStep ( content ) and
424
408
not isNonLocal ( input .head ( ) ) and
@@ -457,6 +441,7 @@ private predicate hasWithContentSummary(
457
441
SummaryComponentStack output
458
442
) {
459
443
exists ( DataFlow:: ContentSet content |
444
+ not TypeTrackingStep:: suppressSummary ( callable ) and
460
445
callable .propagatesFlow ( push ( SummaryComponent:: withContent ( content ) , input ) , output , true ) and
461
446
filter = getFilterFromWithContentStep ( content ) and
462
447
not isNonLocal ( input .head ( ) ) and
@@ -501,6 +486,7 @@ private predicate dependsOnSummaryComponentStack(
501
486
SummarizedCallable callable , SummaryComponentStack stack
502
487
) {
503
488
exists ( callable .getACallSimple ( ) ) and
489
+ not TypeTrackingStep:: suppressSummary ( callable ) and
504
490
(
505
491
callable .propagatesFlow ( stack , _, true )
506
492
or
@@ -585,6 +571,13 @@ class TypeTrackingStep extends TUnit {
585
571
/** Gets the string `"unit"`. */
586
572
string toString ( ) { result = "unit" }
587
573
574
+ /**
575
+ * Holds if type-tracking should not attempt to derive steps from (simple) calls to `callable`.
576
+ *
577
+ * This can be done to manually control how steps are generated from such calls.
578
+ */
579
+ predicate suppressSummary ( SummarizedCallable callable ) { none ( ) }
580
+
588
581
/**
589
582
* Holds if type-tracking should step from `pred` to `succ`.
590
583
*/
@@ -623,6 +616,15 @@ class TypeTrackingStep extends TUnit {
623
616
624
617
/** Provides access to the steps contributed by subclasses of `SharedTypeTrackingStep`. */
625
618
module TypeTrackingStep {
619
+ /**
620
+ * Holds if type-tracking should not attempt to derive steps from (simple) calls to `callable`.
621
+ *
622
+ * This can be done to manually control how steps are generated from such calls.
623
+ */
624
+ predicate suppressSummary ( SummarizedCallable callable ) {
625
+ any ( TypeTrackingStep st ) .suppressSummary ( callable )
626
+ }
627
+
626
628
/**
627
629
* Holds if type-tracking should step from `pred` to `succ`.
628
630
*/
0 commit comments