Skip to content

Commit b9b6ffe

Browse files
authored
Merge pull request #178 from github/cfg_cleanup
Clean up CFG implementation
2 parents ad036f8 + 778de74 commit b9b6ffe

3 files changed

Lines changed: 374 additions & 526 deletions

File tree

ql/src/codeql_ruby/controlflow/internal/ControlFlowGraphImpl.qll

Lines changed: 93 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ module CfgScope {
5858

5959
private class EndBlockScope extends Range_, EndBlock {
6060
final override predicate entry(AstNode first) {
61-
first(this.(Trees::EndBlockTree).getFirstChildNode(), first)
61+
first(this.(Trees::EndBlockTree).getBodyChild(0, _), first)
6262
}
6363

6464
final override predicate exit(AstNode last, Completion c) {
65-
last(this.(Trees::EndBlockTree).getLastChildNode(), last, c)
65+
last(this.(Trees::EndBlockTree).getLastBodyChild(), last, c)
6666
}
6767
}
6868

@@ -76,11 +76,11 @@ module CfgScope {
7676

7777
private class BraceBlockScope extends Range_, BraceBlock {
7878
final override predicate entry(AstNode first) {
79-
first(this.(Trees::BraceBlockTree).getFirstChildNode(), first)
79+
first(this.(Trees::BraceBlockTree).getBodyChild(0, _), first)
8080
}
8181

8282
final override predicate exit(AstNode last, Completion c) {
83-
last(this.(Trees::BraceBlockTree).getLastChildNode(), last, c)
83+
last(this.(Trees::BraceBlockTree).getLastBodyChild(), last, c)
8484
}
8585
}
8686
}
@@ -308,6 +308,8 @@ module Trees {
308308
final override predicate first(AstNode first) { this.firstInner(first) }
309309

310310
final override predicate last(AstNode last, Completion c) { this.lastInner(last, c) }
311+
312+
final override predicate propagatesAbnormal(AstNode child) { none() }
311313
}
312314

313315
private class BinaryOperationTree extends StandardPostOrderTree, BinaryOperation {
@@ -343,11 +345,9 @@ module Trees {
343345

344346
private class BlockParameterTree extends NonDefaultValueParameterTree, BlockParameter { }
345347

346-
/**
347-
* TODO: make all StmtSequence tree classes post-order, and simplify class
348-
* hierarchy.
349-
*/
350348
abstract class BodyStmtTree extends StmtSequenceTree, BodyStmt {
349+
override predicate first(AstNode first) { first = this }
350+
351351
predicate firstInner(AstNode first) {
352352
first(this.getBodyChild(0, _), first)
353353
or
@@ -528,38 +528,33 @@ module Trees {
528528
}
529529
}
530530

531-
abstract class BodyStmtPreOrderTree extends BodyStmtTree, PreOrderTree {
532-
final override predicate last(AstNode last, Completion c) {
533-
this.lastInner(last, c)
534-
or
535-
not exists(this.getAChild(_)) and
536-
last = this and
537-
c.isValidFor(this)
538-
}
531+
private class BooleanLiteralTree extends LeafTree, BooleanLiteral { }
539532

540-
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
541-
BodyStmtTree.super.succ(pred, succ, c)
533+
class BraceBlockTree extends StmtSequenceTree, BraceBlock {
534+
final override predicate propagatesAbnormal(AstNode child) { none() }
535+
536+
final override AstNode getBodyChild(int i, boolean rescuable) {
537+
result = this.getParameter(i) and rescuable = false
542538
or
543-
pred = this and
544-
c instanceof SimpleCompletion and
545-
this.firstInner(succ)
539+
result = StmtSequenceTree.super.getBodyChild(i - this.getNumberOfParameters(), rescuable)
546540
}
547-
}
548541

549-
abstract class BodyStmtPostOrderTree extends BodyStmtTree, PostOrderTree {
550542
override predicate first(AstNode first) { first = this }
551-
}
552-
553-
private class BooleanLiteralTree extends LeafTree, BooleanLiteral { }
554543

555-
class BraceBlockTree extends ScopeTree, BraceBlock {
556-
final override ControlFlowTree getChildNode(int i) {
557-
result = this.getParameter(i)
558-
or
559-
result = this.getStmt(i - this.getNumberOfParameters())
544+
override predicate succ(AstNode pred, AstNode succ, Completion c) {
545+
// Normal left-to-right evaluation in the body
546+
exists(int i |
547+
last(this.getBodyChild(i, _), pred, c) and
548+
first(this.getBodyChild(i + 1, _), succ) and
549+
c instanceof NormalCompletion
550+
)
560551
}
561552
}
562553

554+
private class CallTree extends StandardPostOrderTree, Call {
555+
override ControlFlowTree getChildNode(int i) { result = this.getArgument(i) }
556+
}
557+
563558
private class CaseTree extends PreOrderTree, CaseExpr {
564559
final override predicate propagatesAbnormal(AstNode child) {
565560
child = this.getValue() or child = this.getABranch()
@@ -603,7 +598,7 @@ module Trees {
603598

604599
private class CharacterTree extends LeafTree, CharacterLiteral { }
605600

606-
private class ClassDeclarationTree extends BodyStmtPreOrderTree, ClassDeclaration {
601+
private class ClassDeclarationTree extends NamespaceTree, ClassDeclaration {
607602
/** Gets the `i`th child in the body of this block. */
608603
final override AstNode getBodyChild(int i, boolean rescuable) {
609604
result = this.getScopeExpr() and i = 0 and rescuable = false
@@ -612,8 +607,10 @@ module Trees {
612607
i = count(this.getScopeExpr()) and
613608
rescuable = true
614609
or
615-
result = this.getStmt(i - count(this.getScopeExpr()) - count(this.getSuperclassExpr())) and
616-
rescuable = true
610+
result =
611+
super
612+
.getBodyChild(i - count(this.getScopeExpr()) - count(this.getSuperclassExpr()),
613+
rescuable)
617614
}
618615
}
619616

@@ -749,19 +746,30 @@ module Trees {
749746
final override predicate succ(AstNode pred, AstNode succ, Completion c) { none() }
750747
}
751748

752-
private class DoBlockTree extends BodyStmtPostOrderTree, DoBlock {
749+
private class DoBlockTree extends BodyStmtTree, DoBlock {
753750
/** Gets the `i`th child in the body of this block. */
754751
final override AstNode getBodyChild(int i, boolean rescuable) {
755752
result = this.getParameter(i) and rescuable = false
756753
or
757-
result = BodyStmtPostOrderTree.super.getBodyChild(i - this.getNumberOfParameters(), rescuable)
754+
result = BodyStmtTree.super.getBodyChild(i - this.getNumberOfParameters(), rescuable)
758755
}
756+
757+
override predicate propagatesAbnormal(AstNode child) { none() }
759758
}
760759

761760
private class EmptyStatementTree extends LeafTree, EmptyStmt { }
762761

763-
class EndBlockTree extends ScopeTree, EndBlock {
764-
final override ControlFlowTree getChildNode(int i) { result = this.getStmt(i) }
762+
class EndBlockTree extends StmtSequenceTree, EndBlock {
763+
override predicate first(AstNode first) { first = this }
764+
765+
override predicate succ(AstNode pred, AstNode succ, Completion c) {
766+
// Normal left-to-right evaluation in the body
767+
exists(int i |
768+
last(this.getBodyChild(i, _), pred, c) and
769+
first(this.getBodyChild(i + 1, _), succ) and
770+
c instanceof NormalCompletion
771+
)
772+
}
765773
}
766774

767775
private class ForInTree extends LeafTree, ForIn { }
@@ -871,12 +879,12 @@ module Trees {
871879
final override AstNode getAccessNode() { result = this.getDefiningAccess() }
872880
}
873881

874-
private class LambdaTree extends BodyStmtPostOrderTree, Lambda {
882+
private class LambdaTree extends BodyStmtTree, Lambda {
875883
/** Gets the `i`th child in the body of this block. */
876884
final override AstNode getBodyChild(int i, boolean rescuable) {
877885
result = this.getParameter(i) and rescuable = false
878886
or
879-
result = BodyStmtPostOrderTree.super.getBodyChild(i - this.getNumberOfParameters(), rescuable)
887+
result = BodyStmtTree.super.getBodyChild(i - this.getNumberOfParameters(), rescuable)
880888
}
881889
}
882890

@@ -934,33 +942,51 @@ module Trees {
934942
}
935943
}
936944

937-
private class MethodCallTree extends StandardPostOrderTree, MethodCall {
945+
private class MethodCallTree extends CallTree, MethodCall {
938946
final override ControlFlowTree getChildNode(int i) {
939947
result = this.getReceiver() and i = 0
940948
or
941-
result = this.getArgument(i - count(this.getReceiver()))
949+
result = this.getArgument(i - 1)
942950
or
943-
result = this.getBlock() and i = count(this.getReceiver()) + this.getNumberOfArguments()
951+
result = this.getBlock() and i = 1 + this.getNumberOfArguments()
944952
}
945953
}
946954

947955
private class MethodNameTree extends LeafTree, MethodName, ASTInternal::TTokenMethodName { }
948956

949-
private class MethodTree extends BodyStmtPostOrderTree, Method {
957+
private class MethodTree extends BodyStmtTree, Method {
958+
final override predicate propagatesAbnormal(AstNode child) { none() }
959+
950960
/** Gets the `i`th child in the body of this block. */
951961
final override AstNode getBodyChild(int i, boolean rescuable) {
952962
result = this.getParameter(i) and rescuable = false
953963
or
954-
result = BodyStmtPostOrderTree.super.getBodyChild(i - this.getNumberOfParameters(), rescuable)
964+
result = BodyStmtTree.super.getBodyChild(i - this.getNumberOfParameters(), rescuable)
955965
}
956966
}
957967

958-
private class ModuleDeclarationTree extends BodyStmtPreOrderTree, ModuleDeclaration {
968+
private class ModuleDeclarationTree extends NamespaceTree, ModuleDeclaration {
959969
/** Gets the `i`th child in the body of this block. */
960970
final override AstNode getBodyChild(int i, boolean rescuable) {
961971
result = this.getScopeExpr() and i = 0 and rescuable = false
962972
or
963-
result = BodyStmtPreOrderTree.super.getBodyChild(i - count(this.getScopeExpr()), rescuable)
973+
result = NamespaceTree.super.getBodyChild(i - count(this.getScopeExpr()), rescuable)
974+
}
975+
}
976+
977+
private class NamespaceTree extends BodyStmtTree, Namespace {
978+
final override predicate first(AstNode first) {
979+
this.firstInner(first)
980+
or
981+
not exists(this.getAChild(_)) and
982+
first = this
983+
}
984+
985+
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
986+
BodyStmtTree.super.succ(pred, succ, c)
987+
or
988+
succ = this and
989+
this.lastInner(pred, c)
964990
}
965991
}
966992

@@ -1106,88 +1132,43 @@ module Trees {
11061132
SimpleParameterTreeDupUnderscore() { not exists(this.getDefiningAccess()) }
11071133
}
11081134

1109-
/**
1110-
* Control-flow tree for any post-order StmtSequence that doesn't have a more
1111-
* specific implementation.
1112-
* TODO: make all StmtSequence tree classes post-order, and simplify class
1113-
* hierarchy.
1114-
*/
1115-
private class SimplePostOrderStmtSequenceTree extends StmtSequenceTree, PostOrderTree {
1116-
SimplePostOrderStmtSequenceTree() {
1117-
this instanceof StringInterpolationComponent or
1118-
this instanceof ParenthesizedExpr
1119-
}
1120-
1121-
final override predicate first(AstNode first) { first(this.getStmt(0), first) }
1122-
1123-
final override predicate propagatesAbnormal(AstNode child) { child = this.getAStmt() }
1124-
1125-
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
1126-
succ = this and
1127-
last(this.getLastBodyChild(), pred, c) and
1128-
c instanceof NormalCompletion
1129-
or
1130-
StmtSequenceTree.super.succ(pred, succ, c)
1131-
}
1132-
}
1133-
1134-
/**
1135-
* Control-flow tree for any pre-order StmtSequence that doesn't have a more
1136-
* specific implementation.
1137-
* TODO: make all StmtSequence tree classes post-order, and simplify class
1138-
* hierarchy.
1139-
*/
1140-
private class SimplePreOrderStmtSequenceTree extends StmtSequenceTree, PreOrderTree {
1141-
SimplePreOrderStmtSequenceTree() {
1142-
not this instanceof BodyStmtTree and
1143-
not this instanceof EndBlock and
1144-
not this instanceof StringInterpolationComponent and
1145-
not this instanceof Block and
1146-
not this instanceof ParenthesizedExpr
1147-
}
1148-
1149-
final override predicate propagatesAbnormal(AstNode child) { child = this.getAStmt() }
1150-
1151-
final override predicate last(AstNode last, Completion c) {
1152-
last(this.getLastStmt(), last, c)
1135+
private class SingletonClassTree extends BodyStmtTree, SingletonClass {
1136+
final override predicate first(AstNode first) {
1137+
this.firstInner(first)
11531138
or
1154-
not exists(this.getLastStmt()) and
1155-
c.isValidFor(this) and
1156-
last = this
1139+
not exists(this.getAChild(_)) and
1140+
first = this
11571141
}
11581142

11591143
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
1160-
pred = this and
1161-
first(this.getBodyChild(0, _), succ) and
1162-
c instanceof SimpleCompletion
1144+
BodyStmtTree.super.succ(pred, succ, c)
11631145
or
1164-
StmtSequenceTree.super.succ(pred, succ, c)
1146+
succ = this and
1147+
this.lastInner(pred, c)
11651148
}
1166-
}
11671149

1168-
private class SingletonClassTree extends BodyStmtPreOrderTree, SingletonClass {
11691150
/** Gets the `i`th child in the body of this block. */
11701151
final override AstNode getBodyChild(int i, boolean rescuable) {
11711152
(
11721153
result = this.getValue() and i = 0 and rescuable = false
11731154
or
1174-
result = BodyStmtPreOrderTree.super.getBodyChild(i - 1, rescuable)
1155+
result = BodyStmtTree.super.getBodyChild(i - 1, rescuable)
11751156
)
11761157
}
11771158
}
11781159

1179-
private class SingletonMethodTree extends BodyStmtPostOrderTree, SingletonMethod {
1160+
private class SingletonMethodTree extends BodyStmtTree, SingletonMethod {
11801161
/** Gets the `i`th child in the body of this block. */
11811162
final override AstNode getBodyChild(int i, boolean rescuable) {
11821163
result = this.getParameter(i) and rescuable = false
11831164
or
1184-
result = BodyStmtPostOrderTree.super.getBodyChild(i - this.getNumberOfParameters(), rescuable)
1165+
result = BodyStmtTree.super.getBodyChild(i - this.getNumberOfParameters(), rescuable)
11851166
}
11861167

11871168
override predicate first(AstNode first) { first(this.getObject(), first) }
11881169

11891170
override predicate succ(AstNode pred, AstNode succ, Completion c) {
1190-
BodyStmtPostOrderTree.super.succ(pred, succ, c)
1171+
BodyStmtTree.super.succ(pred, succ, c)
11911172
or
11921173
last(this.getObject(), pred, c) and
11931174
succ = this and
@@ -1201,8 +1182,10 @@ module Trees {
12011182

12021183
private class SplatParameterTree extends NonDefaultValueParameterTree, SplatParameter { }
12031184

1204-
abstract class StmtSequenceTree extends ControlFlowTree, StmtSequence {
1205-
override predicate propagatesAbnormal(AstNode child) { none() }
1185+
class StmtSequenceTree extends PostOrderTree, StmtSequence {
1186+
override predicate propagatesAbnormal(AstNode child) { child = this.getAStmt() }
1187+
1188+
override predicate first(AstNode first) { first(this.getStmt(0), first) }
12061189

12071190
/** Gets the `i`th child in the body of this body statement. */
12081191
AstNode getBodyChild(int i, boolean rescuable) {
@@ -1224,6 +1207,10 @@ module Trees {
12241207
first(this.getBodyChild(i + 1, _), succ) and
12251208
c instanceof NormalCompletion
12261209
)
1210+
or
1211+
succ = this and
1212+
last(this.getLastBodyChild(), pred, c) and
1213+
c instanceof NormalCompletion
12271214
}
12281215
}
12291216

@@ -1243,10 +1230,6 @@ module Trees {
12431230
final override ControlFlowTree getChildNode(int i) { result = this.getComponent(i) }
12441231
}
12451232

1246-
private class SuperCallTree extends StandardPostOrderTree, SuperCall {
1247-
final override ControlFlowTree getChildNode(int i) { result = this.getArgument(i) }
1248-
}
1249-
12501233
private class ToplevelTree extends BodyStmtTree, Toplevel {
12511234
final override AstNode getBodyChild(int i, boolean rescuable) {
12521235
result = this.getBeginBlock(i) and rescuable = true
@@ -1313,11 +1296,6 @@ module Trees {
13131296
)
13141297
}
13151298
}
1316-
1317-
// TODO: make post-order
1318-
private class YieldCallTree extends StandardPreOrderTree, YieldCall {
1319-
final override ControlFlowTree getChildNode(int i) { result = this.getArgument(i) }
1320-
}
13211299
}
13221300

13231301
private Scope parent(Scope n) {

0 commit comments

Comments
 (0)