mirror of
https://github.com/github/codeql.git
synced 2026-05-03 20:58:03 +02:00
ruby: drop special handling of for-in loops in the CFG
This commit is contained in:
@@ -132,7 +132,6 @@ private module Cached {
|
||||
TFalseLiteral(Ruby::False g) or
|
||||
TFloatLiteral(Ruby::Float g) { not any(Ruby::Rational r).getChild() = g } or
|
||||
TForExpr(Ruby::For g) or
|
||||
TForIn(Ruby::In g) or // TODO REMOVE
|
||||
TForwardParameter(Ruby::ForwardParameter g) or
|
||||
TForwardArgument(Ruby::ForwardArgument g) or
|
||||
TGEExpr(Ruby::Binary g) { g instanceof @ruby_binary_rangleequal } or
|
||||
@@ -389,7 +388,6 @@ private module Cached {
|
||||
n = TFalseLiteral(result) or
|
||||
n = TFloatLiteral(result) or
|
||||
n = TForExpr(result) or
|
||||
n = TForIn(result) or // TODO REMOVE
|
||||
n = TForwardArgument(result) or
|
||||
n = TForwardParameter(result) or
|
||||
n = TGEExpr(result) or
|
||||
|
||||
@@ -54,9 +54,6 @@ private predicate nestedEnsureCompletion(Completion outer, int nestLevel) {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate completionIsValidForStmt(AstNode n, Completion c) {
|
||||
n = TForIn(_) and
|
||||
c instanceof EmptinessCompletion
|
||||
or
|
||||
n instanceof BreakStmt and
|
||||
c = TBreakCompletion()
|
||||
or
|
||||
|
||||
@@ -91,25 +91,6 @@ predicate succEntry(CfgScope::Range_ scope, AstNode first) { scope.entry(first)
|
||||
pragma[nomagic]
|
||||
predicate succExit(CfgScope::Range_ scope, AstNode last, Completion c) { scope.exit(last, c) }
|
||||
|
||||
// TODO: remove this class; it should be replaced with an implicit non AST node
|
||||
private class ForIn extends AstNode, ASTInternal::TForIn {
|
||||
final override string toString() { result = "In" }
|
||||
}
|
||||
|
||||
// TODO: remove this class; it should be replaced with an implicit non AST node
|
||||
private class ForRange extends ForExpr {
|
||||
override AstNode getAChild(string pred) {
|
||||
result = super.getAChild(pred)
|
||||
or
|
||||
pred = "<in>" and
|
||||
result = this.getIn()
|
||||
}
|
||||
|
||||
ForIn getIn() {
|
||||
result = ASTInternal::TForIn(ASTInternal::toGenerated(this).(Ruby::For).getValue())
|
||||
}
|
||||
}
|
||||
|
||||
/** Defines the CFG by dispatch on the various AST types. */
|
||||
module Trees {
|
||||
private class AliasStmtTree extends StandardPreOrderTree, AliasStmt {
|
||||
@@ -610,89 +591,6 @@ module Trees {
|
||||
|
||||
private class ForwardParameterTree extends LeafTree, ForwardParameter { }
|
||||
|
||||
private class ForInTree extends LeafTree, ForIn { }
|
||||
|
||||
/**
|
||||
* Control flow of a for-in loop
|
||||
*
|
||||
* For example, this program fragment:
|
||||
*
|
||||
* ```rb
|
||||
* for arg in args do
|
||||
* puts arg
|
||||
* end
|
||||
* puts "done";
|
||||
* ```
|
||||
*
|
||||
* has the following control flow graph:
|
||||
*
|
||||
* ```
|
||||
* args
|
||||
* |
|
||||
* in------<-----
|
||||
* / \ \
|
||||
* / \ |
|
||||
* / \ |
|
||||
* / \ |
|
||||
* empty non-empty |
|
||||
* | \ |
|
||||
* for \ |
|
||||
* | arg |
|
||||
* | | |
|
||||
* puts "done" puts arg |
|
||||
* \___/
|
||||
* ```
|
||||
*/
|
||||
private class ForTree extends PostOrderTree, ForRange {
|
||||
final override predicate propagatesAbnormal(AstNode child) {
|
||||
child = this.getPattern() or child = this.getValue()
|
||||
}
|
||||
|
||||
final override predicate first(AstNode first) { first(this.getValue(), first) }
|
||||
|
||||
/**
|
||||
* for pattern in array do body end
|
||||
* ```
|
||||
* array +-> in +--[non empty]--> pattern -> body -> in
|
||||
* |--[empty]--> for
|
||||
* ```
|
||||
*/
|
||||
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
last(this.getValue(), pred, c) and
|
||||
first(this.getIn(), succ) and
|
||||
c instanceof SimpleCompletion
|
||||
or
|
||||
last(this.getIn(), pred, c) and
|
||||
first(this.getPattern(), succ) and
|
||||
c.(EmptinessCompletion).getValue() = false
|
||||
or
|
||||
last(this.getPattern(), pred, c) and
|
||||
first(this.getBody(), succ) and
|
||||
c instanceof NormalCompletion
|
||||
or
|
||||
last(this.getBody(), pred, c) and
|
||||
first(this.getIn(), succ) and
|
||||
c.continuesLoop()
|
||||
or
|
||||
last(this.getBody(), pred, c) and
|
||||
first(this.getBody(), succ) and
|
||||
c instanceof RedoCompletion
|
||||
or
|
||||
succ = this and
|
||||
(
|
||||
last(this.getIn(), pred, c) and
|
||||
c.(EmptinessCompletion).getValue() = true
|
||||
or
|
||||
last(this.getBody(), pred, c) and
|
||||
not c.continuesLoop() and
|
||||
not c instanceof BreakCompletion and
|
||||
not c instanceof RedoCompletion
|
||||
or
|
||||
last(this.getBody(), pred, c.(NestedBreakCompletion).getAnInnerCompatibleCompletion())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class GlobalVariableTree extends LeafTree, GlobalVariableAccess { }
|
||||
|
||||
private class HashLiteralTree extends StandardPostOrderTree, HashLiteral {
|
||||
|
||||
Reference in New Issue
Block a user