Skip to content

Commit

Permalink
Ruby: Adopt shared ConditionalCompletionSplitting implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
hvitved committed Oct 3, 2024
1 parent 8172930 commit 2e8bfea
Showing 1 changed file with 41 additions and 30 deletions.
71 changes: 41 additions & 30 deletions ruby/ql/lib/codeql/ruby/controlflow/internal/Splitting.qll
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
*/

private import codeql.ruby.AST as Ast
private import Completion
private import Completion as Comp
private import Comp
private import ControlFlowGraphImpl
private import SuccessorTypes
private import codeql.ruby.controlflow.ControlFlowGraph
Expand Down Expand Up @@ -64,54 +65,64 @@ private module ConditionalCompletionSplitting {

int getNextListOrder() { result = 1 }

private class ConditionalCompletionSplitImpl extends SplitImpl instanceof ConditionalCompletionSplit
{
ConditionalCompletion completion;

ConditionalCompletionSplitImpl() { this = TConditionalCompletionSplit(completion) }
private module Input implements SplitImplementations::ConditionalCompletionSplittingInputSig {
class ConditionalCompletion = Comp::ConditionalCompletion;

override ConditionalCompletionSplitKind getKind() { any() }
class ConditionalCompletionSplitImpl = ConditionalCompletionSplitImpl_;

override predicate hasEntry(AstNode pred, AstNode succ, Completion c) {
succ(pred, succ, c) and
last(succ, _, completion) and
bindingset[parent, parentCompletion]
predicate condPropagateExpr(
AstNode parent, ConditionalCompletion parentCompletion, AstNode child,
ConditionalCompletion childCompletion
) {
child = parent.(Ast::NotExpr).getOperand() and
childCompletion.(BooleanCompletion).getDual() = parentCompletion
or
childCompletion = parentCompletion and
(
last(succ.(Ast::NotExpr).getOperand(), pred, c) and
completion.(BooleanCompletion).getDual() = c
or
last(succ.(Ast::LogicalAndExpr).getAnOperand(), pred, c) and
completion = c
child = parent.(Ast::LogicalAndExpr).getAnOperand()
or
last(succ.(Ast::LogicalOrExpr).getAnOperand(), pred, c) and
completion = c
child = parent.(Ast::LogicalOrExpr).getAnOperand()
or
last(succ.(Ast::StmtSequence).getLastStmt(), pred, c) and
completion = c
child = parent.(Ast::StmtSequence).getLastStmt()
or
last(succ.(Ast::ConditionalExpr).getBranch(_), pred, c) and
completion = c
child = parent.(Ast::ConditionalExpr).getBranch(_)
)
}
}

private class SharedImpl =
SplitImplementations::ConditionalCompletionSplitting<Input>::ConditionalCompletionSplit;

private class ConditionalCompletionSplitImpl_ extends SplitImpl instanceof ConditionalCompletionSplit
{
ConditionalCompletion getCompletion() { this = TConditionalCompletionSplit(result) }

override ConditionalCompletionSplitKind getKind() { any() }

override predicate hasEntry(AstNode pred, AstNode succ, Completion c) {
this.(SharedImpl).hasEntry(pred, succ, c)
or
succ(pred, succ, c) and
succ instanceof Ast::WhenClause and
completion = c
c = this.getCompletion()
}

override predicate hasEntryScope(CfgScope scope, AstNode succ) { none() }
override predicate hasEntryScope(CfgScope scope, AstNode first) {
this.(SharedImpl).hasEntryScope(scope, first)
}

override predicate hasExit(AstNode pred, AstNode succ, Completion c) {
this.appliesTo(pred) and
succ(pred, succ, c) and
if c instanceof ConditionalCompletion then completion = c else any()
this.(SharedImpl).hasExit(pred, succ, c)
}

override predicate hasExitScope(CfgScope scope, AstNode last, Completion c) {
this.appliesTo(last) and
succExit(scope, last, c) and
if c instanceof ConditionalCompletion then completion = c else any()
this.(SharedImpl).hasExitScope(scope, last, c)
}

override predicate hasSuccessor(AstNode pred, AstNode succ, Completion c) { none() }
override predicate hasSuccessor(AstNode pred, AstNode succ, Completion c) {
this.(SharedImpl).hasSuccessor(pred, succ, c)
}
}
}

Expand Down

0 comments on commit 2e8bfea

Please sign in to comment.