Skip to content

Commit aa8751c

Browse files
committed
Ruby: revome cases where the loop may be interrupted
1 parent 13724c8 commit aa8751c

File tree

1 file changed

+20
-1
lines changed

1 file changed

+20
-1
lines changed

ruby/ql/src/queries/performance/CouldBeAsync.ql

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
*/
1010

1111
import ruby
12+
private import codeql.ruby.AST
1213
import codeql.ruby.Concepts
1314
import codeql.ruby.frameworks.ActiveRecord
15+
private import codeql.ruby.TaintTracking
1416

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

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

62+
// The ActiveRecord instance is used to potentially control the loop
63+
predicate usedInLoopControlGuard(ActiveRecordInstance ar, DataFlow::Node guard) {
64+
TaintTracking::localTaint(ar, guard) and
65+
guard = guardForLoopControl(_, _)
66+
}
67+
68+
// A guard for controlling the loop
69+
DataFlow::Node guardForLoopControl(ConditionalExpr cond, Stmt control) {
70+
result.asExpr().getAstNode() = cond.getCondition().getAChild*() and
71+
(
72+
control.(MethodCall).getMethodName() = "raise"
73+
or
74+
control instanceof NextStmt
75+
) and
76+
control = cond.getBranch(_).getAChild()
77+
}
78+
6179
from LoopingCall loop, DataFlow::CallNode call, string message
6280
where
6381
not call.getLocation().getFile().getAbsolutePath().matches("%test%") and
6482
not call = any(PluckCall p).chaines() and
83+
not usedInLoopControlGuard(call, _) and
6584
happensInInnermostLoop(loop, call) and
6685
(
6786
call instanceof ActiveRecordModelFinderCall and

0 commit comments

Comments
 (0)