Skip to content

Commit

Permalink
Ruby: revome cases where the loop may be interrupted
Browse files Browse the repository at this point in the history
  • Loading branch information
yoff committed Jan 14, 2025
1 parent 51ecf48 commit 5d3a541
Showing 1 changed file with 20 additions and 1 deletion.
21 changes: 20 additions & 1 deletion ruby/ql/src/queries/performance/CouldBeAsync.ql
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
*/

import ruby
private import codeql.ruby.AST
import codeql.ruby.Concepts
import codeql.ruby.frameworks.ActiveRecord
private import codeql.ruby.TaintTracking

string loopMethodName() {
result in [
Expand All @@ -33,7 +35,6 @@ predicate happensInLoop(LoopingCall loop, DataFlow::CallNode e) {
loop.getLoopBlock().asCallableAstNode() = e.asExpr().getScope()
}

// predicate directLoop(@ruby_while)
predicate happensInOuterLoop(LoopingCall outerLoop, DataFlow::CallNode e) {
exists(LoopingCall innerLoop |
happensInLoop(outerLoop, innerLoop) and
Expand All @@ -58,10 +59,28 @@ private ActiveRecordInstance getChain(ActiveRecordInstanceMethodCall c) {
result = getChain(c.getInstance())
}

// The ActiveRecord instance is used to potentially control the loop
predicate usedInLoopControlGuard(ActiveRecordInstance ar, DataFlow::Node guard) {
TaintTracking::localTaint(ar, guard) and
guard = guardForLoopControl(_, _)
}

// A guard for controlling the loop
DataFlow::Node guardForLoopControl(ConditionalExpr cond, Stmt control) {
result.asExpr().getAstNode() = cond.getCondition().getAChild*() and
(
control.(MethodCall).getMethodName() = "raise"
or
control instanceof NextStmt
) and
control = cond.getBranch(_).getAChild()
}

from LoopingCall loop, DataFlow::CallNode call, string message
where
not call.getLocation().getFile().getAbsolutePath().matches("%test%") and
not call = any(PluckCall p).chaines() and
not usedInLoopControlGuard(call, _) and
happensInInnermostLoop(loop, call) and
(
call instanceof ActiveRecordModelFinderCall and
Expand Down

0 comments on commit 5d3a541

Please sign in to comment.