Skip to content

Commit bde04d4

Browse files
authored
Merge pull request #116 from github/aibaars/cfg-loop-post-order
CFG: make loop expressions post order
2 parents 37c4e6c + f2a6f3a commit bde04d4

4 files changed

Lines changed: 129 additions & 106 deletions

File tree

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ private predicate nestedEnsureCompletion(Completion outer, int nestLevel) {
5454

5555
pragma[noinline]
5656
private predicate completionIsValidForStmt(AstNode n, Completion c) {
57+
n instanceof In and
58+
c instanceof EmptinessCompletion
59+
or
5760
n instanceof Break and
5861
c = TBreakCompletion()
5962
or

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

Lines changed: 50 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -339,15 +339,14 @@ private class LeftToRightPostOrderTree extends StandardPostOrderTree, LeftToRigh
339339
}
340340

341341
private class LeftToRightPreOrderNodes =
342-
@alias or @block_parameters or @class or @do or @else or @ensure or @in or @lambda_parameters or
342+
@alias or @block_parameters or @class or @do or @else or @ensure or @lambda_parameters or
343343
@method_parameters or @pattern or @program or @then or @undef or @yield;
344344

345345
private class LeftToRightPreOrderTree extends StandardPreOrderTree, LeftToRightPreOrderNodes {
346346
override predicate isHidden() {
347347
this instanceof BlockParameters or
348348
this instanceof Do or
349349
this instanceof Else or
350-
this instanceof In or
351350
this instanceof LambdaParameters or
352351
this instanceof MethodParameters or
353352
this instanceof Pattern or
@@ -593,66 +592,71 @@ module Trees {
593592
* ```
594593
* args
595594
* |
596-
* for------<-----
595+
* in------<-----
597596
* / \ \
598597
* / \ |
599598
* / \ |
600599
* / \ |
601600
* empty non-empty |
602601
* | \ |
603-
* puts "done" \ |
604-
* arg |
605-
* | |
606-
* puts arg |
602+
* for \ |
603+
* | arg |
604+
* | | |
605+
* puts "done" puts arg |
607606
* \___/
608607
* ```
609608
*/
610-
private class ForTree extends ControlFlowTree, For {
609+
private class ForTree extends PostOrderTree, For {
611610
final override predicate propagatesAbnormal(AstNode child) {
612-
child = this.getPattern() or child = this.getValue()
611+
child = this.getPattern() or child = this.getArray()
613612
}
614613

615-
final override predicate first(AstNode node) { node = this.getValue() }
614+
final override predicate first(AstNode first) { first(this.getArray(), first) }
616615

617-
final override predicate last(AstNode last, Completion c) {
618-
last = this and
619-
c.(EmptinessCompletion).getValue() = true
620-
or
621-
last(this.getBody(), last, c) and
622-
not c.continuesLoop() and
623-
not c instanceof BreakCompletion and
624-
not c instanceof RedoCompletion
625-
or
626-
last(this.getBody(), last, c.(NestedBreakCompletion).getAnInnerCompatibleCompletion())
627-
}
616+
private In getIn() { result = this.getValue() }
617+
618+
private UnderscoreArg getArray() { result = this.getValue().getChild() }
628619

629620
/**
630-
* for pattern in value do body end
621+
* for pattern in array do body end
631622
* ```
632-
* value +-> for +--[non empty]--> pattern -> body -> for
633-
* |--[empty]--> exit
623+
* array +-> in +--[non empty]--> pattern -> body -> in
624+
* |--[empty]--> for
634625
* ```
635626
*/
636627
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
637-
last(this.getValue(), pred, c) and
638-
succ = this and
628+
last(this.getArray(), pred, c) and
629+
first(this.getIn(), succ) and
639630
c instanceof SimpleCompletion
640631
or
641-
pred = this and
632+
last(this.getIn(), pred, c) and
642633
first(this.getPattern(), succ) and
643634
c.(EmptinessCompletion).getValue() = false
644635
or
645-
first(this.getBody(), succ) and
646636
last(this.getPattern(), pred, c) and
637+
first(this.getBody(), succ) and
647638
c instanceof NormalCompletion
648639
or
649640
last(this.getBody(), pred, c) and
650-
succ = this and
641+
first(this.getIn(), succ) and
651642
c.continuesLoop()
652643
or
653644
last(this.getBody(), pred, c) and
654645
first(this.getBody(), succ) and
655646
c instanceof RedoCompletion
647+
or
648+
succ = this and
649+
(
650+
last(this.getIn(), pred, c) and
651+
c.(EmptinessCompletion).getValue() = true
652+
or
653+
last(this.getBody(), pred, c) and
654+
not c.continuesLoop() and
655+
not c instanceof BreakCompletion and
656+
not c instanceof RedoCompletion
657+
or
658+
last(this.getBody(), pred, c.(NestedBreakCompletion).getAnInnerCompatibleCompletion())
659+
)
656660
}
657661
}
658662

@@ -712,6 +716,8 @@ module Trees {
712716
}
713717
}
714718

719+
private class InTree extends LeafTree, In { }
720+
715721
private class InstanceVariableTree extends LeafTree, InstanceVariable { }
716722

717723
private class IntegerTree extends LeafTree, Integer { }
@@ -1224,26 +1230,12 @@ module Trees {
12241230
}
12251231
}
12261232

1227-
private class ConditionalLoopTree extends PreOrderTree, ConditionalLoopAstNode {
1233+
private class ConditionalLoopTree extends PostOrderTree, ConditionalLoopAstNode {
12281234
final override predicate propagatesAbnormal(AstNode child) { child = this.getConditionNode() }
12291235

1230-
final override predicate last(AstNode last, Completion c) {
1231-
last(this.getConditionNode(), last, c) and
1232-
this.endLoop(c)
1233-
or
1234-
last(this.getBodyNode(), last, c) and
1235-
not c.continuesLoop() and
1236-
not c instanceof BreakCompletion and
1237-
not c instanceof RedoCompletion
1238-
or
1239-
last(this.getBodyNode(), last, c.(NestedBreakCompletion).getAnInnerCompatibleCompletion())
1240-
}
1236+
final override predicate first(AstNode first) { first(this.getConditionNode(), first) }
12411237

12421238
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
1243-
pred = this and
1244-
first(this.getConditionNode(), succ) and
1245-
c instanceof SimpleCompletion
1246-
or
12471239
last(this.getConditionNode(), pred, c) and
12481240
this.continueLoop(c) and
12491241
first(this.getBodyNode(), succ)
@@ -1255,6 +1247,19 @@ module Trees {
12551247
last(this.getBodyNode(), pred, c) and
12561248
first(this.getBodyNode(), succ) and
12571249
c instanceof RedoCompletion
1250+
or
1251+
succ = this and
1252+
(
1253+
last(this.getConditionNode(), pred, c) and
1254+
this.endLoop(c)
1255+
or
1256+
last(this.getBodyNode(), pred, c) and
1257+
not c.continuesLoop() and
1258+
not c instanceof BreakCompletion and
1259+
not c instanceof RedoCompletion
1260+
or
1261+
last(this.getBodyNode(), pred, c.(NestedBreakCompletion).getAnInnerCompatibleCompletion())
1262+
)
12581263
}
12591264
}
12601265
}

0 commit comments

Comments
 (0)