Skip to content

Commit 91b917b

Browse files
committed
Ruby: Split callable and its body into two AST nodes.
1 parent cb0fc78 commit 91b917b

15 files changed

Lines changed: 159 additions & 98 deletions

File tree

ruby/ql/consistency-queries/CfgConsistency.ql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ query predicate scopeNoFirst(CfgScope scope) {
2727
not scope =
2828
any(Callable c |
2929
not exists(c.getAParameter()) and
30-
not c.(BodyStmt).hasEnsure() and
31-
not exists(c.(BodyStmt).getARescue())
30+
not c.getBody().hasEnsure() and
31+
not exists(c.getBody().getARescue())
3232
)
3333
}

ruby/ql/lib/codeql/ruby/ast/Expr.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ class StmtSequence extends Expr, TStmtSequence {
167167
*/
168168
class BodyStmt extends StmtSequence, TBodyStmt {
169169
final override Stmt getStmt(int n) {
170+
synthChild(this, n, result)
171+
or
170172
toGenerated(result) =
171173
rank[n + 1](Ruby::AstNode node, int i |
172174
node = getBodyStmtChild(this, i) and

ruby/ql/lib/codeql/ruby/ast/Method.qll

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ private import internal.TreeSitter
88
private import internal.Method
99

1010
/** A callable. */
11-
class Callable extends StmtSequence, Expr, Scope, TCallable {
11+
class Callable extends Expr, Scope, TCallable {
1212
/** Gets the number of parameters of this callable. */
1313
final int getNumberOfParameters() { result = count(this.getAParameter()) }
1414

@@ -18,27 +18,26 @@ class Callable extends StmtSequence, Expr, Scope, TCallable {
1818
/** Gets the `n`th parameter of this callable. */
1919
Parameter getParameter(int n) { none() }
2020

21+
/** Gets the body of this callable. */
22+
BodyStmt getBody() { none() }
23+
2124
override AstNode getAChild(string pred) {
2225
result = super.getAChild(pred)
2326
or
27+
pred = "getBody" and result = this.getBody()
28+
or
2429
pred = "getParameter" and result = this.getParameter(_)
2530
}
2631
}
2732

2833
/** A method. */
29-
class MethodBase extends Callable, BodyStmt, Scope, TMethodBase {
34+
class MethodBase extends Callable, Scope, TMethodBase {
3035
/** Gets the name of this method. */
3136
string getName() { none() }
3237

3338
/** Holds if the name of this method is `name`. */
3439
final predicate hasName(string name) { this.getName() = name }
3540

36-
override AstNode getAChild(string pred) {
37-
result = Callable.super.getAChild(pred)
38-
or
39-
result = BodyStmt.super.getAChild(pred)
40-
}
41-
4241
/**
4342
* Holds if this method is public.
4443
* Methods are public by default.
@@ -218,6 +217,10 @@ class Method extends MethodBase, TMethod {
218217
toGenerated(result) = g.getParameters().getChild(n)
219218
}
220219

220+
final override BodyStmt getBody() {
221+
toGenerated(result) = g.getBody() or synthChild(this, _, result)
222+
}
223+
221224
final override string toString() { result = this.getName() }
222225

223226
overlay[global]
@@ -280,6 +283,10 @@ class SingletonMethod extends MethodBase, TSingletonMethod {
280283
toGenerated(result) = g.getParameters().getChild(n)
281284
}
282285

286+
final override BodyStmt getBody() {
287+
toGenerated(result) = g.getBody() or synthChild(this, _, result)
288+
}
289+
283290
final override string toString() { result = this.getName() }
284291

285292
final override AstNode getAChild(string pred) {
@@ -321,7 +328,7 @@ class SingletonMethod extends MethodBase, TSingletonMethod {
321328
* -> (x) { x + 1 }
322329
* ```
323330
*/
324-
class Lambda extends Callable, BodyStmt, TLambda {
331+
class Lambda extends Callable, TLambda {
325332
private Ruby::Lambda g;
326333

327334
Lambda() { this = TLambda(g) }
@@ -332,13 +339,12 @@ class Lambda extends Callable, BodyStmt, TLambda {
332339
toGenerated(result) = g.getParameters().getChild(n)
333340
}
334341

335-
final override string toString() { result = "-> { ... }" }
336-
337-
final override AstNode getAChild(string pred) {
338-
result = Callable.super.getAChild(pred)
339-
or
340-
result = BodyStmt.super.getAChild(pred)
342+
final override BodyStmt getBody() {
343+
toGenerated(result) = g.getBody().(Ruby::DoBlock).getBody() or
344+
toGenerated(result) = g.getBody().(Ruby::Block).getBody()
341345
}
346+
347+
final override string toString() { result = "-> { ... }" }
342348
}
343349

344350
/** A block. */
@@ -355,15 +361,15 @@ class Block extends Callable, Scope, TBlock {
355361
*/
356362
LocalVariableWriteAccess getLocalVariable(int n) { none() }
357363

358-
override AstNode getAChild(string pred) {
364+
final override AstNode getAChild(string pred) {
359365
result = Callable.super.getAChild(pred)
360366
or
361367
pred = "getLocalVariable" and result = this.getLocalVariable(_)
362368
}
363369
}
364370

365371
/** A block enclosed within `do` and `end`. */
366-
class DoBlock extends Block, BodyStmt, TDoBlock {
372+
class DoBlock extends Block, TDoBlock {
367373
private Ruby::DoBlock g;
368374

369375
DoBlock() { this = TDoBlock(g) }
@@ -376,13 +382,9 @@ class DoBlock extends Block, BodyStmt, TDoBlock {
376382
toGenerated(result) = g.getParameters().getChild(n)
377383
}
378384

379-
final override string toString() { result = "do ... end" }
385+
final override BodyStmt getBody() { toGenerated(result) = g.getBody() }
380386

381-
final override AstNode getAChild(string pred) {
382-
result = Block.super.getAChild(pred)
383-
or
384-
result = BodyStmt.super.getAChild(pred)
385-
}
387+
final override string toString() { result = "do ... end" }
386388

387389
final override string getAPrimaryQlClass() { result = "DoBlock" }
388390
}

ruby/ql/lib/codeql/ruby/ast/internal/AST.qll

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,16 @@ private module Cached {
100100
} or
101101
TBlockArgument(Ruby::BlockArgument g) or
102102
TBlockParameter(Ruby::BlockParameter g) or
103+
TBodyStatement(Ruby::BodyStatement g) {
104+
any(Ruby::Method m).getBody() = g or
105+
any(Ruby::SingletonMethod m).getBody() = g or
106+
any(Ruby::DoBlock b).getBody() = g
107+
} or
108+
TBodyStmtSynth(Ast::AstNode parent, int i) { mkSynthChild(BodyStmtKind(), parent, i) } or
103109
TBooleanLiteralSynth(Ast::AstNode parent, int i, boolean value) {
104110
mkSynthChild(BooleanLiteralKind(value), parent, i)
105111
} or
112+
TBraceBlockBody(Ruby::BlockBody g) or
106113
TBraceBlockSynth(Ast::AstNode parent, int i) { mkSynthChild(BraceBlockKind(), parent, i) } or
107114
TBraceBlockReal(Ruby::Block g) { not g.getParent() instanceof Ruby::Lambda } or
108115
TBreakStmt(Ruby::Break g) or
@@ -362,23 +369,24 @@ private module Cached {
362369
TAssignMulExpr or TAssignRShiftExpr or TAssignSubExpr or TBareStringLiteral or
363370
TBareSymbolLiteral or TBeginBlock or TBeginExpr or TBitwiseAndExprReal or
364371
TBitwiseOrExprReal or TBitwiseXorExprReal or TBlockArgument or TBlockParameter or
365-
TBraceBlockReal or TBreakStmt or TCaseEqExpr or TCaseExpr or TCaseMatchReal or
366-
TCharacterLiteral or TClassDeclaration or TClassVariableAccessReal or TComplementExpr or
367-
TComplexLiteral or TDefinedExprReal or TDelimitedSymbolLiteral or
368-
TDestructuredLeftAssignment or TDestructuredParameter or TDivExprReal or TDo or TDoBlock or
369-
TElementReference or TElseReal or TElsif or TEmptyStmt or TEncoding or TEndBlock or
370-
TEnsure or TEqExpr or TExponentExprReal or TFalseLiteral or TFile or TFindPattern or
371-
TFloatLiteral or TForExpr or TForwardParameter or TForwardArgument or TGEExpr or TGTExpr or
372-
TGlobalVariableAccessReal or THashKeySymbolLiteral or THashLiteral or THashPattern or
373-
THashSplatExprReal or THashSplatNilParameter or THashSplatParameter or THereDoc or
374-
TIdentifierMethodCall or TIfReal or TIfModifierExpr or TInClauseReal or
375-
TInstanceVariableAccessReal or TIntegerLiteralReal or TKeywordParameter or TLEExpr or
376-
TLShiftExprReal or TLTExpr or TLambda or TLeftAssignmentList or TLine or
377-
TLocalVariableAccessReal or TLogicalAndExprReal or TLogicalOrExprReal or TMethod or
378-
TMatchPattern or TModuleDeclaration or TModuloExprReal or TMulExprReal or TNEExpr or
379-
TNextStmt or TNilLiteralReal or TNoRegExpMatchExpr or TNotExprReal or TOptionalParameter or
380-
TPairReal or TParenthesizedExpr or TParenthesizedPattern or TRShiftExprReal or
381-
TRangeLiteralReal or TRationalLiteral or TRedoStmt or TRegExpLiteral or TRegExpMatchExpr or
372+
TBodyStatement or TBraceBlockBody or TBraceBlockReal or TBreakStmt or TCaseEqExpr or
373+
TCaseExpr or TCaseMatchReal or TCharacterLiteral or TClassDeclaration or
374+
TClassVariableAccessReal or TComplementExpr or TComplexLiteral or TDefinedExprReal or
375+
TDelimitedSymbolLiteral or TDestructuredLeftAssignment or TDestructuredParameter or
376+
TDivExprReal or TDo or TDoBlock or TElementReference or TElseReal or TElsif or TEmptyStmt or
377+
TEncoding or TEndBlock or TEnsure or TEqExpr or TExponentExprReal or TFalseLiteral or
378+
TFile or TFindPattern or TFloatLiteral or TForExpr or TForwardParameter or
379+
TForwardArgument or TGEExpr or TGTExpr or TGlobalVariableAccessReal or
380+
THashKeySymbolLiteral or THashLiteral or THashPattern or THashSplatExprReal or
381+
THashSplatNilParameter or THashSplatParameter or THereDoc or TIdentifierMethodCall or
382+
TIfReal or TIfModifierExpr or TInClauseReal or TInstanceVariableAccessReal or
383+
TIntegerLiteralReal or TKeywordParameter or TLEExpr or TLShiftExprReal or TLTExpr or
384+
TLambda or TLeftAssignmentList or TLine or TLocalVariableAccessReal or
385+
TLogicalAndExprReal or TLogicalOrExprReal or TMethod or TMatchPattern or
386+
TModuleDeclaration or TModuloExprReal or TMulExprReal or TNEExpr or TNextStmt or
387+
TNilLiteralReal or TNoRegExpMatchExpr or TNotExprReal or TOptionalParameter or TPairReal or
388+
TParenthesizedExpr or TParenthesizedPattern or TRShiftExprReal or TRangeLiteralReal or
389+
TRationalLiteral or TRedoStmt or TRegExpLiteral or TRegExpMatchExpr or
382390
TRegularArrayLiteral or TRegularMethodCall or TRegularStringLiteral or TRegularSuperCall or
383391
TRescueClause or TRescueModifierExpr or TRetryStmt or TReturnStmt or
384392
TScopeResolutionConstantAccess or TSelfReal or TSimpleParameterReal or
@@ -393,13 +401,13 @@ private module Cached {
393401

394402
class TAstNodeSynth =
395403
TAddExprSynth or TAssignExprSynth or TBitwiseAndExprSynth or TBitwiseOrExprSynth or
396-
TBitwiseXorExprSynth or TBraceBlockSynth or TBooleanLiteralSynth or TCaseMatchSynth or
397-
TClassVariableAccessSynth or TConstantReadAccessSynth or TConstantWriteAccessSynth or
398-
TDivExprSynth or TElseSynth or TExponentExprSynth or TGlobalVariableAccessSynth or
399-
TIfSynth or TInClauseSynth or TInstanceVariableAccessSynth or TIntegerLiteralSynth or
400-
TLShiftExprSynth or TLocalVariableAccessSynth or TLogicalAndExprSynth or
401-
TLogicalOrExprSynth or TMethodCallSynth or TModuloExprSynth or TMulExprSynth or
402-
TNilLiteralSynth or TRShiftExprSynth or TRangeLiteralSynth or TSelfSynth or
404+
TBitwiseXorExprSynth or TBraceBlockSynth or TBodyStmtSynth or TBooleanLiteralSynth or
405+
TCaseMatchSynth or TClassVariableAccessSynth or TConstantReadAccessSynth or
406+
TConstantWriteAccessSynth or TDivExprSynth or TElseSynth or TExponentExprSynth or
407+
TGlobalVariableAccessSynth or TIfSynth or TInClauseSynth or TInstanceVariableAccessSynth or
408+
TIntegerLiteralSynth or TLShiftExprSynth or TLocalVariableAccessSynth or
409+
TLogicalAndExprSynth or TLogicalOrExprSynth or TMethodCallSynth or TModuloExprSynth or
410+
TMulExprSynth or TNilLiteralSynth or TRShiftExprSynth or TRangeLiteralSynth or TSelfSynth or
403411
TSimpleParameterSynth or TSplatExprSynth or THashSplatExprSynth or TStmtSequenceSynth or
404412
TSubExprSynth or TPairSynth or TSimpleSymbolLiteralSynth;
405413

@@ -439,6 +447,8 @@ private module Cached {
439447
n = TBitwiseXorExprReal(result) or
440448
n = TBlockArgument(result) or
441449
n = TBlockParameter(result) or
450+
n = TBodyStatement(result) or
451+
n = TBraceBlockBody(result) or
442452
n = TBraceBlockReal(result) or
443453
n = TBreakStmt(result) or
444454
n = TCaseEqExpr(result) or
@@ -584,6 +594,8 @@ private module Cached {
584594
or
585595
result = TBitwiseXorExprSynth(parent, i)
586596
or
597+
result = TBodyStmtSynth(parent, i)
598+
or
587599
result = TBooleanLiteralSynth(parent, i, _)
588600
or
589601
result = TBraceBlockSynth(parent, i)
@@ -757,9 +769,9 @@ class TElse = TElseReal or TElseSynth;
757769

758770
class TStmtSequence =
759771
TBeginBlock or TEndBlock or TThen or TElse or TDo or TEnsure or TStringInterpolationComponent or
760-
TBlock or TBodyStmt or TParenthesizedExpr or TStmtSequenceSynth;
772+
TBodyStmt or TParenthesizedExpr or TStmtSequenceSynth;
761773

762-
class TBodyStmt = TBeginExpr or TModuleBase or TMethod or TLambda or TDoBlock or TSingletonMethod;
774+
class TBodyStmt = TBeginExpr or TModuleBase or TBraceBlockBody or TBodyStatement or TBodyStmtSynth;
763775

764776
class TNilLiteral = TNilLiteralReal or TNilLiteralSynth;
765777

ruby/ql/lib/codeql/ruby/ast/internal/Expr.qll

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,18 @@ class StmtSequenceSynth extends StmtSequence, TStmtSequenceSynth {
1414
final override string toString() { result = "..." }
1515
}
1616

17+
class BodyStatement extends BodyStmt, TBodyStatement {
18+
final override string toString() { result = "..." }
19+
}
20+
21+
class BraceBlockBody extends BodyStmt, TBraceBlockBody {
22+
final override string toString() { result = "..." }
23+
}
24+
25+
class BodyStmtSynth extends BodyStmt, TBodyStmtSynth {
26+
final override string toString() { result = "..." }
27+
}
28+
1729
class Then extends StmtSequence, TThen {
1830
private Ruby::Then g;
1931

@@ -64,27 +76,31 @@ class Ensure extends StmtSequence, TEnsure {
6476

6577
// Not defined by dispatch, as it should not be exposed
6678
Ruby::AstNode getBodyStmtChild(TBodyStmt b, int i) {
67-
exists(Ruby::Method g, Ruby::AstNode body | b = TMethod(g) and body = g.getBody() |
68-
result = body.(Ruby::BodyStatement).getChild(i)
69-
or
70-
i = 0 and result = body and not body instanceof Ruby::BodyStatement
71-
)
72-
or
73-
exists(Ruby::SingletonMethod g, Ruby::AstNode body |
74-
b = TSingletonMethod(g) and body = g.getBody()
75-
|
76-
result = body.(Ruby::BodyStatement).getChild(i)
77-
or
78-
i = 0 and result = body and not body instanceof Ruby::BodyStatement
79-
)
80-
or
81-
exists(Ruby::Lambda g | b = TLambda(g) |
82-
result = g.getBody().(Ruby::DoBlock).getBody().getChild(i) or
83-
result = g.getBody().(Ruby::Block).getBody().getChild(i)
84-
)
79+
result = any(Ruby::BlockBody g | b = TBraceBlockBody(g)).getChild(i)
8580
or
86-
result = any(Ruby::DoBlock g | b = TDoBlock(g)).getBody().getChild(i)
81+
result = any(Ruby::BodyStatement g | b = TBodyStatement(g)).getChild(i)
8782
or
83+
// exists(Ruby::Method g, Ruby::AstNode body | b = TMethod(g) and body = g.getBody() |
84+
// result = body.(Ruby::BodyStatement).getChild(i)
85+
// or
86+
// i = 0 and result = body and not body instanceof Ruby::BodyStatement
87+
// )
88+
// or
89+
// exists(Ruby::SingletonMethod g, Ruby::AstNode body |
90+
// b = TSingletonMethod(g) and body = g.getBody()
91+
// |
92+
// result = body.(Ruby::BodyStatement).getChild(i)
93+
// or
94+
// i = 0 and result = body and not body instanceof Ruby::BodyStatement
95+
// )
96+
// or
97+
// exists(Ruby::Lambda g | b = TLambda(g) |
98+
// result = g.getBody().(Ruby::DoBlock).getBody().getChild(i) or
99+
// result = g.getBody().(Ruby::Block).getBody().getChild(i)
100+
// )
101+
// or
102+
// result = any(Ruby::DoBlock g | b = TDoBlock(g)).getBody().getChild(i)
103+
// or
88104
result = any(Ruby::Program g | b = TToplevel(g)).getChild(i) and
89105
not result instanceof Ruby::BeginBlock
90106
or

ruby/ql/lib/codeql/ruby/ast/internal/Method.qll

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class BraceBlockReal extends BraceBlock, TBraceBlockReal {
1818
toGenerated(result) = g.getParameters().getChild(n)
1919
}
2020

21-
final override Stmt getStmt(int i) { toGenerated(result) = g.getBody().getChild(i) }
21+
final override BodyStmt getBody() { toGenerated(result) = g.getBody() }
2222
}
2323

2424
/**
@@ -28,8 +28,5 @@ class BraceBlockReal extends BraceBlock, TBraceBlockReal {
2828
class BraceBlockSynth extends BraceBlock, TBraceBlockSynth {
2929
final override Parameter getParameter(int n) { synthChild(this, n, result) }
3030

31-
final override Stmt getStmt(int i) {
32-
i >= 0 and
33-
synthChild(this, i + this.getNumberOfParameters(), result)
34-
}
31+
final override BodyStmt getBody() { synthChild(this, _, result) }
3532
}

0 commit comments

Comments
 (0)