@@ -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
@@ -61,6 +60,15 @@ class ContentFilter extends TContentFilter {
61
60
}
62
61
}
63
62
63
+ /** Module for getting `ContentFilter` values. */
64
+ module ContentFilter {
65
+ /** Gets the filter that only allow element contents. */
66
+ ContentFilter hasElements ( ) { result = MkElementFilter ( ) }
67
+
68
+ /** Gets the filter that only allow pair-value contents. */
69
+ ContentFilter hasPairValue ( ) { result = MkPairValueFilter ( ) }
70
+ }
71
+
64
72
/**
65
73
* Holds if a value stored with `storeContents` can be read back with `loadContents`.
66
74
*/
@@ -226,28 +234,9 @@ predicate basicStoreStep(Node nodeFrom, Node nodeTo, DataFlow::ContentSet conten
226
234
nodeTo = evaluateSummaryComponentStackLocal ( callable , call , output )
227
235
)
228
236
or
229
- // Hash literals
230
- exists ( Cfg:: CfgNodes:: ExprNodes:: PairCfgNode pair |
231
- hashLiteralStore ( nodeTo , any ( DataFlow:: Node n | n .asExpr ( ) = pair ) ) and
232
- nodeFrom .asExpr ( ) = pair .getValue ( )
233
- |
234
- exists ( ConstantValue constant |
235
- constant = pair .getKey ( ) .getConstantValue ( ) and
236
- contents .isSingleton ( DataFlow:: Content:: getElementContent ( constant ) )
237
- )
238
- or
239
- not exists ( pair .getKey ( ) .getConstantValue ( ) ) and
240
- contents .isAnyElement ( )
241
- )
242
- or
243
237
TypeTrackingStep:: storeStep ( nodeFrom , nodeTo , contents )
244
238
}
245
239
246
- private predicate hashLiteralStore ( DataFlow:: CallNode hashCreation , DataFlow:: Node argument ) {
247
- hashCreation .getExprNode ( ) .getExpr ( ) = Hash:: getAStaticHashCall ( "[]" ) and
248
- argument = hashCreation .getArgument ( _)
249
- }
250
-
251
240
/**
252
241
* Holds if a store step `nodeFrom -> nodeTo` with `contents` exists, where the destination node
253
242
* is a post-update node that should be treated as a local source node.
@@ -343,14 +332,6 @@ predicate basicWithContentStep(Node nodeFrom, Node nodeTo, ContentFilter filter)
343
332
nodeTo = evaluateSummaryComponentStackLocal ( callable , call , output )
344
333
)
345
334
or
346
- // Hash-splat in a hash literal
347
- exists ( DataFlow:: Node node |
348
- hashLiteralStore ( nodeTo , node ) and
349
- node .asExpr ( ) .getExpr ( ) instanceof HashSplatExpr and
350
- nodeFrom .asExpr ( ) = node .asExpr ( ) .( Cfg:: CfgNodes:: ExprNodes:: UnaryOperationCfgNode ) .getOperand ( ) and
351
- filter = MkElementFilter ( )
352
- )
353
- or
354
335
TypeTrackingStep:: withContentStep ( nodeFrom , nodeTo , filter )
355
336
}
356
337
@@ -368,6 +349,7 @@ private predicate hasStoreSummary(
368
349
SummarizedCallable callable , DataFlow:: ContentSet contents , SummaryComponentStack input ,
369
350
SummaryComponentStack output
370
351
) {
352
+ not TypeTrackingStep:: suppressSummary ( callable ) and
371
353
callable .propagatesFlow ( input , push ( SummaryComponent:: content ( contents ) , output ) , true ) and
372
354
not isNonLocal ( input .head ( ) ) and
373
355
not isNonLocal ( output .head ( ) )
@@ -378,6 +360,7 @@ private predicate hasLoadSummary(
378
360
SummarizedCallable callable , DataFlow:: ContentSet contents , SummaryComponentStack input ,
379
361
SummaryComponentStack output
380
362
) {
363
+ not TypeTrackingStep:: suppressSummary ( callable ) and
381
364
callable .propagatesFlow ( push ( SummaryComponent:: content ( contents ) , input ) , output , true ) and
382
365
not isNonLocal ( input .head ( ) ) and
383
366
not isNonLocal ( output .head ( ) )
@@ -388,12 +371,12 @@ private predicate hasLoadStoreSummary(
388
371
SummarizedCallable callable , DataFlow:: ContentSet loadContents ,
389
372
DataFlow:: ContentSet storeContents , SummaryComponentStack input , SummaryComponentStack output
390
373
) {
374
+ not TypeTrackingStep:: suppressSummary ( callable ) and
391
375
callable
392
376
.propagatesFlow ( push ( SummaryComponent:: content ( loadContents ) , input ) ,
393
377
push ( SummaryComponent:: content ( storeContents ) , output ) , true ) and
394
378
not isNonLocal ( input .head ( ) ) and
395
- not isNonLocal ( output .head ( ) ) and
396
- callable != "Hash.[]" // Special-cased due to having a huge number of summaries
379
+ not isNonLocal ( output .head ( ) )
397
380
}
398
381
399
382
/**
@@ -426,6 +409,7 @@ private predicate hasWithoutContentSummary(
426
409
SummaryComponentStack output
427
410
) {
428
411
exists ( DataFlow:: ContentSet content |
412
+ not TypeTrackingStep:: suppressSummary ( callable ) and
429
413
callable .propagatesFlow ( push ( SummaryComponent:: withoutContent ( content ) , input ) , output , true ) and
430
414
filter = getFilterFromWithoutContentStep ( content ) and
431
415
not isNonLocal ( input .head ( ) ) and
@@ -464,6 +448,7 @@ private predicate hasWithContentSummary(
464
448
SummaryComponentStack output
465
449
) {
466
450
exists ( DataFlow:: ContentSet content |
451
+ not TypeTrackingStep:: suppressSummary ( callable ) and
467
452
callable .propagatesFlow ( push ( SummaryComponent:: withContent ( content ) , input ) , output , true ) and
468
453
filter = getFilterFromWithContentStep ( content ) and
469
454
not isNonLocal ( input .head ( ) ) and
@@ -508,6 +493,7 @@ private predicate dependsOnSummaryComponentStack(
508
493
SummarizedCallable callable , SummaryComponentStack stack
509
494
) {
510
495
exists ( callable .getACallSimple ( ) ) and
496
+ not TypeTrackingStep:: suppressSummary ( callable ) and
511
497
(
512
498
callable .propagatesFlow ( stack , _, true )
513
499
or
@@ -592,6 +578,13 @@ class TypeTrackingStep extends TUnit {
592
578
/** Gets the string `"unit"`. */
593
579
string toString ( ) { result = "unit" }
594
580
581
+ /**
582
+ * Holds if type-tracking should not attempt to derive steps from (simple) calls to `callable`.
583
+ *
584
+ * This can be done to manually control how steps are generated from such calls.
585
+ */
586
+ predicate suppressSummary ( SummarizedCallable callable ) { none ( ) }
587
+
595
588
/**
596
589
* Holds if type-tracking should step from `pred` to `succ`.
597
590
*/
@@ -630,6 +623,15 @@ class TypeTrackingStep extends TUnit {
630
623
631
624
/** Provides access to the steps contributed by subclasses of `SharedTypeTrackingStep`. */
632
625
module TypeTrackingStep {
626
+ /**
627
+ * Holds if type-tracking should not attempt to derive steps from (simple) calls to `callable`.
628
+ *
629
+ * This can be done to manually control how steps are generated from such calls.
630
+ */
631
+ predicate suppressSummary ( SummarizedCallable callable ) {
632
+ any ( TypeTrackingStep st ) .suppressSummary ( callable )
633
+ }
634
+
633
635
/**
634
636
* Holds if type-tracking should step from `pred` to `succ`.
635
637
*/
0 commit comments