1
1
package io .joern .rubysrc2cpg .astcreation
2
2
3
3
import io .joern .rubysrc2cpg .astcreation .RubyIntermediateAst .{
4
+ ArrayLiteral ,
4
5
ArrayPattern ,
5
6
BinaryExpression ,
6
7
BreakExpression ,
7
8
CaseExpression ,
8
9
ControlFlowStatement ,
9
10
DoWhileExpression ,
11
+ DummyAst ,
12
+ DynamicLiteral ,
10
13
ElseClause ,
11
14
ForExpression ,
12
15
IfExpression ,
@@ -17,10 +20,9 @@ import io.joern.rubysrc2cpg.astcreation.RubyIntermediateAst.{
17
20
NextExpression ,
18
21
OperatorAssignment ,
19
22
RescueExpression ,
20
- ReturnExpression ,
21
23
RubyExpression ,
22
- SimpleCall ,
23
24
SimpleIdentifier ,
25
+ SimpleObjectInstantiation ,
24
26
SingleAssignment ,
25
27
SplattingRubyNode ,
26
28
StatementList ,
@@ -32,18 +34,12 @@ import io.joern.rubysrc2cpg.astcreation.RubyIntermediateAst.{
32
34
WhenClause ,
33
35
WhileExpression
34
36
}
35
- import io .joern .rubysrc2cpg .parser . RubyJsonHelpers
37
+ import io .joern .rubysrc2cpg .datastructures . BlockScope
36
38
import io .joern .rubysrc2cpg .passes .Defines
37
- import io .joern .rubysrc2cpg .passes .Defines .RubyOperators
39
+ import io .joern .rubysrc2cpg .passes .Defines .getBuiltInType
38
40
import io .joern .x2cpg .{Ast , ValidationMode }
41
+ import io .shiftleft .codepropertygraph .generated .nodes .{NewBlock , NewFieldIdentifier , NewLiteral , NewLocal }
39
42
import io .shiftleft .codepropertygraph .generated .{ControlStructureTypes , DispatchTypes , Operators }
40
- import io .shiftleft .codepropertygraph .generated .nodes .{
41
- NewBlock ,
42
- NewFieldIdentifier ,
43
- NewIdentifier ,
44
- NewLiteral ,
45
- NewLocal
46
- }
47
43
48
44
trait AstForControlStructuresCreator (implicit withSchemaValidation : ValidationMode ) { this : AstCreator =>
49
45
@@ -335,16 +331,67 @@ trait AstForControlStructuresCreator(implicit withSchemaValidation: ValidationMo
335
331
ifElseChain.iterator.toList
336
332
}
337
333
338
- def generatedNode : StatementList = node.expression
339
- .map { e =>
340
- val tmp = SimpleIdentifier (None )(e.span.spanStart(this .tmpGen.fresh))
341
- StatementList (
342
- List (SingleAssignment (tmp, " =" , e)(e.span)) ++
343
- goCase(Some (tmp))
344
- )(node.span)
334
+ val caseExpr = node.expression
335
+ .map {
336
+ case arrayLiteral : ArrayLiteral =>
337
+ val tmp = SimpleIdentifier (None )(arrayLiteral.span.spanStart(this .tmpGen.fresh))
338
+ val arrayLiteralAst = DummyAst (astForTempArray(arrayLiteral))(arrayLiteral.span)
339
+ (tmp, arrayLiteralAst)
340
+ case e =>
341
+ val tmp = SimpleIdentifier (None )(e.span.spanStart(this .tmpGen.fresh))
342
+ (tmp, e)
345
343
}
344
+ .map((tmp, e) => StatementList (List (SingleAssignment (tmp, " =" , e)(e.span)) ++ goCase(Some (tmp)))(node.span))
346
345
.getOrElse(StatementList (goCase(None ))(node.span))
347
- astsForStatement(generatedNode)
346
+
347
+ astsForStatement(caseExpr)
348
+ }
349
+
350
+ private def astForTempArray (node : ArrayLiteral ): Ast = {
351
+ val tmp = this .tmpGen.fresh
352
+
353
+ def tmpRubyNode (tmpNode : Option [RubyExpression ] = None ) =
354
+ SimpleIdentifier ()(tmpNode.map(_.span).getOrElse(node.span).spanStart(tmp))
355
+
356
+ def tmpAst (tmpNode : Option [RubyExpression ] = None ) = astForSimpleIdentifier(tmpRubyNode(tmpNode))
357
+
358
+ val block = blockNode(node, node.text, Defines .Any )
359
+ scope.pushNewScope(BlockScope (block))
360
+ val tmpLocal = NewLocal ().name(tmp).code(tmp)
361
+ scope.addToScope(tmp, tmpLocal)
362
+
363
+ val arguments = if (node.text.startsWith(" %" )) {
364
+ val argumentsType =
365
+ if (node.isStringArray) getBuiltInType(Defines .String )
366
+ else getBuiltInType(Defines .Symbol )
367
+ node.elements.map {
368
+ case element @ StaticLiteral (_) => StaticLiteral (argumentsType)(element.span)
369
+ case element @ DynamicLiteral (_, expressions) => DynamicLiteral (argumentsType, expressions)(element.span)
370
+ case element => element
371
+ }
372
+ } else {
373
+ node.elements
374
+ }
375
+ val argumentAsts = arguments.zipWithIndex.map { case (arg, idx) =>
376
+ val indices = StaticLiteral (getBuiltInType(Defines .Integer ))(arg.span.spanStart(idx.toString)) :: Nil
377
+ val base = tmpRubyNode(Option (arg))
378
+ val indexAccess = IndexAccess (base, indices)(arg.span.spanStart(s " ${base.text}[ $idx] " ))
379
+ val assignment = SingleAssignment (indexAccess, " =" , arg)(arg.span.spanStart(s " ${indexAccess.text} = ${arg.text}" ))
380
+ astForExpression(assignment)
381
+ }
382
+
383
+ val arrayInitCall = {
384
+ val base = SimpleIdentifier ()(node.span.spanStart(Defines .Array ))
385
+ astForExpression(SimpleObjectInstantiation (base, Nil )(node.span))
386
+ }
387
+
388
+ val assignment =
389
+ callNode(node, code(node), Operators .assignment, Operators .assignment, DispatchTypes .STATIC_DISPATCH )
390
+ val tmpAssignment = callAst(assignment, tmpAst() :: arrayInitCall :: Nil )
391
+ val tmpRetAst = tmpAst(node.elements.lastOption)
392
+
393
+ scope.popScope()
394
+ blockAst(block, tmpAssignment +: argumentAsts :+ tmpRetAst)
348
395
}
349
396
350
397
private def astForOperatorAssignmentExpression (node : OperatorAssignment ): Ast = {
0 commit comments