@@ -10,6 +10,7 @@ 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
13
14
14
15
class Node = DataFlowPublic:: Node ;
15
16
@@ -220,6 +221,25 @@ predicate basicStoreStep(Node nodeFrom, Node nodeTo, DataFlow::ContentSet conten
220
221
nodeFrom = evaluateSummaryComponentStackLocal ( callable , call , input ) and
221
222
nodeTo = evaluateSummaryComponentStackLocal ( callable , call , output )
222
223
)
224
+ or
225
+ // Hash literals
226
+ exists ( Cfg:: CfgNodes:: ExprNodes:: PairCfgNode pair |
227
+ hashLiteralStore ( nodeTo , any ( DataFlow:: Node n | n .asExpr ( ) = pair ) ) and
228
+ nodeFrom .asExpr ( ) = pair .getValue ( )
229
+ |
230
+ exists ( ConstantValue constant |
231
+ constant = pair .getKey ( ) .getConstantValue ( ) and
232
+ contents .isSingleton ( DataFlow:: Content:: getElementContent ( constant ) )
233
+ )
234
+ or
235
+ not exists ( pair .getKey ( ) .getConstantValue ( ) ) and
236
+ contents .isAnyElement ( )
237
+ )
238
+ }
239
+
240
+ private predicate hashLiteralStore ( DataFlow:: CallNode hashCreation , DataFlow:: Node argument ) {
241
+ hashCreation .getExprNode ( ) .getExpr ( ) = Hash:: getAStaticHashCall ( "[]" ) and
242
+ argument = hashCreation .getArgument ( _)
223
243
}
224
244
225
245
/**
@@ -310,6 +330,14 @@ predicate basicWithContentStep(Node nodeFrom, Node nodeTo, ContentFilter filter)
310
330
nodeFrom = evaluateSummaryComponentStackLocal ( callable , call , input ) and
311
331
nodeTo = evaluateSummaryComponentStackLocal ( callable , call , output )
312
332
)
333
+ or
334
+ // Hash-splat in a hash literal
335
+ exists ( DataFlow:: Node node |
336
+ hashLiteralStore ( nodeTo , node ) and
337
+ node .asExpr ( ) .getExpr ( ) instanceof HashSplatExpr and
338
+ nodeFrom .asExpr ( ) = node .asExpr ( ) .( Cfg:: CfgNodes:: ExprNodes:: UnaryOperationCfgNode ) .getOperand ( ) and
339
+ filter = MkElementFilter ( )
340
+ )
313
341
}
314
342
315
343
/**
@@ -344,7 +372,8 @@ private predicate hasLoadStoreSummary(
344
372
) {
345
373
callable
346
374
.propagatesFlow ( push ( SummaryComponent:: content ( loadContents ) , input ) ,
347
- push ( SummaryComponent:: content ( storeContents ) , output ) , true )
375
+ push ( SummaryComponent:: content ( storeContents ) , output ) , true ) and
376
+ callable != "Hash.[]" // Special-cased due to having a huge number of summaries
348
377
}
349
378
350
379
/**
0 commit comments