mirror of
https://github.com/github/codeql.git
synced 2026-05-02 12:15:17 +02:00
CFG
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
|
||||
private import codeql.ruby.AST
|
||||
private import codeql.ruby.ast.internal.AST
|
||||
private import codeql.ruby.ast.internal.Control
|
||||
private import codeql.ruby.controlflow.ControlFlowGraph
|
||||
private import ControlFlowGraphImpl
|
||||
private import NonReturning
|
||||
@@ -100,7 +101,11 @@ abstract class Completion extends TCompletion {
|
||||
or
|
||||
n = any(RescueModifierExpr parent).getBody() and this = TRaiseCompletion()
|
||||
or
|
||||
mayRaise(n) and
|
||||
(
|
||||
mayRaise(n)
|
||||
or
|
||||
n instanceof CaseMatch and not exists(n.(CaseExpr).getElseBranch())
|
||||
) and
|
||||
this = TRaiseCompletion()
|
||||
or
|
||||
not n instanceof NonReturningCall and
|
||||
@@ -172,6 +177,8 @@ private predicate inBooleanContext(AstNode n) {
|
||||
or
|
||||
n = any(ConditionalLoop parent).getCondition()
|
||||
or
|
||||
n = any(InClause parent).getCondition()
|
||||
or
|
||||
exists(LogicalAndExpr parent |
|
||||
n = parent.getLeftOperand()
|
||||
or
|
||||
@@ -218,6 +225,14 @@ private predicate inMatchingContext(AstNode n) {
|
||||
w.getPattern(_) = n
|
||||
)
|
||||
or
|
||||
n instanceof CasePattern
|
||||
or
|
||||
n = any(ArrayPattern p).getClass()
|
||||
or
|
||||
n = any(FindPattern p).getClass()
|
||||
or
|
||||
n = any(HashPattern p).getClass()
|
||||
or
|
||||
n.(Trees::DefaultValueParameterTree).hasDefaultValue()
|
||||
}
|
||||
|
||||
|
||||
@@ -419,6 +419,352 @@ module Trees {
|
||||
}
|
||||
}
|
||||
|
||||
private class CaseMatchTree extends PreOrderTree, CaseExpr, ASTInternal::TCaseMatch {
|
||||
final override predicate propagatesAbnormal(AstNode child) {
|
||||
child = this.getValue() or child = this.getABranch()
|
||||
}
|
||||
|
||||
final override predicate last(AstNode last, Completion c) {
|
||||
last(this.getABranch(), last, c) and
|
||||
not c.(MatchingCompletion).getValue() = false
|
||||
or
|
||||
not exists(this.getElseBranch()) and
|
||||
exists(Completion lc, Expr lastBranch |
|
||||
lastBranch = max(int i | | this.getBranch(i) order by i) and
|
||||
lc.(MatchingCompletion).getValue() = false and
|
||||
last(lastBranch, last, lc) and
|
||||
c.getInnerCompletion() = lc and
|
||||
c instanceof RaiseCompletion
|
||||
)
|
||||
}
|
||||
|
||||
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
pred = this and
|
||||
first(this.getValue(), succ) and
|
||||
c instanceof SimpleCompletion
|
||||
or
|
||||
last(this.getValue(), pred, c) and
|
||||
first(this.getBranch(0), succ) and
|
||||
c instanceof SimpleCompletion
|
||||
or
|
||||
exists(int i, Expr branch | branch = this.getBranch(i) |
|
||||
last(branch, pred, c) and
|
||||
first(this.getBranch(i + 1), succ) and
|
||||
c.(MatchingCompletion).getValue() = false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class PatternVariableAccessTree extends LocalVariableAccessTree, CasePattern {
|
||||
final override predicate last(AstNode last, Completion c) {
|
||||
super.last(last, c) and
|
||||
c.(MatchingCompletion).getValue() = true
|
||||
}
|
||||
}
|
||||
|
||||
private class ArrayPatternTree extends ControlFlowTree, ArrayPattern {
|
||||
final override predicate propagatesAbnormal(AstNode child) {
|
||||
child = this.getClass() or
|
||||
child = this.getPrefixElement(_) or
|
||||
child = this.getRestVariableAccess() or
|
||||
child = this.getSuffixElement(_)
|
||||
}
|
||||
|
||||
final override predicate first(AstNode first) {
|
||||
first(this.getClass(), first)
|
||||
or
|
||||
not exists(this.getClass()) and first = this
|
||||
}
|
||||
|
||||
final override predicate last(AstNode last, Completion c) {
|
||||
c.(MatchingCompletion).getValue() = false and
|
||||
(
|
||||
last = this
|
||||
or
|
||||
exists(AstNode node |
|
||||
node = this.getClass() or
|
||||
node = this.getPrefixElement(_) or
|
||||
node = this.getSuffixElement(_)
|
||||
|
|
||||
last(node, last, c)
|
||||
)
|
||||
)
|
||||
or
|
||||
c.(MatchingCompletion).getValue() = true and
|
||||
last = this and
|
||||
not exists(this.getPrefixElement(_)) and
|
||||
not exists(this.getRestVariableAccess())
|
||||
or
|
||||
c.(MatchingCompletion).getValue() = true and
|
||||
last(max(int i | | this.getPrefixElement(i) order by i), last, c) and
|
||||
not exists(this.getRestVariableAccess())
|
||||
or
|
||||
last(this.getRestVariableAccess(), last, c) and
|
||||
not exists(this.getSuffixElement(_))
|
||||
or
|
||||
c.(MatchingCompletion).getValue() = true and
|
||||
last(max(int i | | this.getSuffixElement(i) order by i), last, c)
|
||||
}
|
||||
|
||||
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
last(this.getClass(), pred, c) and
|
||||
succ = this and
|
||||
c.(MatchingCompletion).getValue() = true
|
||||
or
|
||||
pred = this and
|
||||
first(this.getPrefixElement(0), succ) and
|
||||
c.(MatchingCompletion).getValue() = true
|
||||
or
|
||||
not exists(this.getPrefixElement(_)) and
|
||||
pred = this and
|
||||
first(this.getRestVariableAccess(), succ) and
|
||||
c.(MatchingCompletion).getValue() = true
|
||||
or
|
||||
last(max(int i | | this.getPrefixElement(i) order by i), pred, c) and
|
||||
first(this.getRestVariableAccess(), succ) and
|
||||
c.(MatchingCompletion).getValue() = true
|
||||
or
|
||||
exists(int i |
|
||||
last(this.getPrefixElement(i), pred, c) and
|
||||
first(this.getPrefixElement(i + 1), succ) and
|
||||
c.(MatchingCompletion).getValue() = true
|
||||
)
|
||||
or
|
||||
last(this.getRestVariableAccess(), pred, c) and
|
||||
first(this.getSuffixElement(0), succ) and
|
||||
c instanceof SimpleCompletion
|
||||
or
|
||||
exists(int i |
|
||||
last(this.getSuffixElement(i), pred, c) and
|
||||
first(this.getSuffixElement(i + 1), succ) and
|
||||
c.(MatchingCompletion).getValue() = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class FindPatternTree extends ControlFlowTree, FindPattern {
|
||||
final override predicate propagatesAbnormal(AstNode child) {
|
||||
child = this.getClass() or
|
||||
child = this.getPrefixVariableAccess() or
|
||||
child = this.getElement(_) or
|
||||
child = this.getSuffixVariableAccess()
|
||||
}
|
||||
|
||||
final override predicate first(AstNode first) {
|
||||
first(this.getClass(), first)
|
||||
or
|
||||
not exists(this.getClass()) and first = this
|
||||
}
|
||||
|
||||
final override predicate last(AstNode last, Completion c) {
|
||||
last(this.getSuffixVariableAccess(), last, c)
|
||||
or
|
||||
last(max(int i | | this.getElement(i) order by i), last, c) and
|
||||
not exists(this.getSuffixVariableAccess())
|
||||
or
|
||||
c.(MatchingCompletion).getValue() = false and
|
||||
(
|
||||
last = this
|
||||
or
|
||||
exists(AstNode node | node = this.getClass() or node = this.getElement(_) |
|
||||
last(node, last, c)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
last(this.getClass(), pred, c) and
|
||||
succ = this and
|
||||
c.(MatchingCompletion).getValue() = true
|
||||
or
|
||||
pred = this and
|
||||
first(this.getPrefixVariableAccess(), succ) and
|
||||
c.(MatchingCompletion).getValue() = true
|
||||
or
|
||||
pred = this and
|
||||
first(this.getElement(0), succ) and
|
||||
not exists(this.getPrefixVariableAccess()) and
|
||||
c.(MatchingCompletion).getValue() = true
|
||||
or
|
||||
last(this.getPrefixVariableAccess(), pred, c) and
|
||||
first(this.getElement(0), succ) and
|
||||
c instanceof SimpleCompletion
|
||||
or
|
||||
c.(MatchingCompletion).getValue() = true and
|
||||
exists(int i |
|
||||
last(this.getElement(i), pred, c) and
|
||||
first(this.getElement(i + 1), succ)
|
||||
)
|
||||
or
|
||||
c.(MatchingCompletion).getValue() = true and
|
||||
last(max(int i | | this.getElement(i) order by i), pred, c) and
|
||||
first(this.getSuffixVariableAccess(), succ)
|
||||
}
|
||||
}
|
||||
|
||||
private class HashPatternTree extends ControlFlowTree, HashPattern {
|
||||
final override predicate propagatesAbnormal(AstNode child) {
|
||||
child = this.getClass() or
|
||||
child = this.getValue(_) or
|
||||
child = this.getRestVariableAccess()
|
||||
}
|
||||
|
||||
final override predicate first(AstNode first) {
|
||||
first(this.getClass(), first)
|
||||
or
|
||||
not exists(this.getClass()) and first = this
|
||||
}
|
||||
|
||||
final override predicate last(AstNode last, Completion c) {
|
||||
c.(MatchingCompletion).getValue() = false and
|
||||
(
|
||||
last = this
|
||||
or
|
||||
exists(AstNode node |
|
||||
node = this.getClass() or
|
||||
node = this.getValue(_)
|
||||
|
|
||||
last(node, last, c)
|
||||
)
|
||||
)
|
||||
or
|
||||
c.(MatchingCompletion).getValue() = true and
|
||||
last = this and
|
||||
not exists(this.getValue(_)) and
|
||||
not exists(this.getRestVariableAccess())
|
||||
or
|
||||
c.(MatchingCompletion).getValue() = true and
|
||||
last(max(int i | | this.getValue(i) order by i), last, c) and
|
||||
not exists(this.getRestVariableAccess())
|
||||
or
|
||||
last(this.getRestVariableAccess(), last, c)
|
||||
}
|
||||
|
||||
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
last(this.getClass(), pred, c) and
|
||||
succ = this and
|
||||
c.(MatchingCompletion).getValue() = true
|
||||
or
|
||||
pred = this and
|
||||
first(this.getValue(0), succ) and
|
||||
c.(MatchingCompletion).getValue() = true
|
||||
or
|
||||
not exists(this.getValue(_)) and
|
||||
pred = this and
|
||||
first(this.getRestVariableAccess(), succ) and
|
||||
c.(MatchingCompletion).getValue() = true
|
||||
or
|
||||
last(max(int i | | this.getValue(i) order by i), pred, c) and
|
||||
first(this.getRestVariableAccess(), succ) and
|
||||
c.(MatchingCompletion).getValue() = true
|
||||
or
|
||||
exists(int i |
|
||||
last(this.getValue(i), pred, c) and
|
||||
first(this.getValue(i + 1), succ) and
|
||||
c.(MatchingCompletion).getValue() = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class LineLiteralTree extends LeafTree, LineLiteral { }
|
||||
|
||||
private class FileLiteralTree extends LeafTree, FileLiteral { }
|
||||
|
||||
private class EncodingLiteralTree extends LeafTree, EncodingLiteral { }
|
||||
|
||||
private class AlternativePatternTree extends PreOrderTree, AlternativePattern {
|
||||
final override predicate propagatesAbnormal(AstNode child) { child = this.getAnAlternative() }
|
||||
|
||||
final override predicate last(AstNode last, Completion c) {
|
||||
last(this.getAnAlternative(), last, c) and
|
||||
c.(MatchingCompletion).getValue() = true
|
||||
or
|
||||
last(max(int i | | this.getAlternative(i) order by i), last, c) and
|
||||
c.(MatchingCompletion).getValue() = false
|
||||
}
|
||||
|
||||
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
pred = this and
|
||||
first(this.getAlternative(0), succ) and
|
||||
c instanceof SimpleCompletion
|
||||
or
|
||||
exists(int i |
|
||||
last(this.getAlternative(i), pred, c) and
|
||||
first(this.getAlternative(i + 1), succ) and
|
||||
c.(MatchingCompletion).getValue() = false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class AsPatternTree extends StandardPreOrderTree, AsPattern {
|
||||
override ControlFlowTree getChildElement(int i) {
|
||||
result = this.getPattern() and i = 0
|
||||
or
|
||||
result = this.getVariableAccess() and i = 1
|
||||
}
|
||||
}
|
||||
|
||||
private class ParenthesizedPatternTree extends StandardPreOrderTree, ParenthesizedPattern {
|
||||
override ControlFlowTree getChildElement(int i) { result = this.getPattern() and i = 0 }
|
||||
}
|
||||
|
||||
private class VariableReferencePatternTree extends StandardPostOrderTree, VariableReferencePattern {
|
||||
override ControlFlowTree getChildElement(int i) { result = this.getVariableAccess() and i = 0 }
|
||||
}
|
||||
|
||||
private class InClauseTree extends PreOrderTree, InClause {
|
||||
final override predicate propagatesAbnormal(AstNode child) {
|
||||
child = this.getPattern() or
|
||||
child = this.getCondition()
|
||||
}
|
||||
|
||||
final override predicate last(AstNode last, Completion c) {
|
||||
last(this.getPattern(), last, c) and
|
||||
c.(MatchingCompletion).getValue() = false
|
||||
or
|
||||
exists(Completion pc |
|
||||
last(this.getCondition(), last, pc) and
|
||||
pc.(ConditionalCompletion).getValue() = false and
|
||||
c.(MatchingCompletion).getValue() = false
|
||||
)
|
||||
or
|
||||
last(this.getBody(), last, c)
|
||||
or
|
||||
not exists(this.getBody()) and last(this.getCondition(), last, c)
|
||||
or
|
||||
not exists(this.getBody()) and
|
||||
not exists(this.getCondition()) and
|
||||
last(this.getPattern(), last, c)
|
||||
}
|
||||
|
||||
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
pred = this and
|
||||
first(this.getPattern(), succ) and
|
||||
c instanceof SimpleCompletion
|
||||
or
|
||||
exists(Expr next |
|
||||
last(this.getPattern(), pred, c) and
|
||||
c.(MatchingCompletion).getValue() = true and
|
||||
first(next, succ)
|
||||
|
|
||||
next = this.getCondition()
|
||||
or
|
||||
not exists(this.getCondition()) and next = this.getBody()
|
||||
)
|
||||
or
|
||||
exists(Completion pc, boolean flag |
|
||||
flag = true and this.hasIfCondition()
|
||||
or
|
||||
flag = false and this.hasUnlessCondition()
|
||||
|
|
||||
last(this.getCondition(), pred, pc) and
|
||||
pc.(ConditionalCompletion).getValue() = flag and
|
||||
first(this.getBody(), succ) and
|
||||
c.(MatchingCompletion).getValue() = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class CharacterTree extends LeafTree, CharacterLiteral { }
|
||||
|
||||
private class ClassDeclarationTree extends NamespaceTree, ClassDeclaration {
|
||||
|
||||
@@ -176,6 +176,7 @@
|
||||
| control/cases.rb:76:13:76:13 | :b | b |
|
||||
| control/cases.rb:84:7:84:8 | 42 | 42 |
|
||||
| control/cases.rb:87:6:87:6 | 5 | 5 |
|
||||
| control/cases.rb:88:7:88:9 | foo | 42 |
|
||||
| control/cases.rb:90:6:90:13 | "string" | string |
|
||||
| control/cases.rb:91:9:91:11 | "foo" | foo |
|
||||
| control/cases.rb:91:13:91:15 | "bar" | bar |
|
||||
|
||||
Reference in New Issue
Block a user