diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/Completion.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/Completion.qll index 83ea11e9d230..b7340473dbe8 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/internal/Completion.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/Completion.qll @@ -69,6 +69,9 @@ private predicate completionIsValidForStmt(AstNode n, Completion c) { or n instanceof ReturnStmt and c = TReturnCompletion() + or + n instanceof RetryStmt and + c = TRetryCompletion() } private AstNode getARescuableBodyChild() { diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll index dd672ba982d7..fc4cc7916bbd 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll @@ -1319,6 +1319,11 @@ module Trees { last(super.getBody(), pred, c) and c instanceof NormalCompletion and succ = this + or + pred = super.getBody().getAStmt().getAChild*() and + pred instanceof RetryStmt and + c instanceof RetryCompletion and + exists(BodyStmtTree stmt | this = stmt.getARescue() | first(stmt, succ)) } } diff --git a/ruby/ql/src/queries/variables/UninitializedLocal.ql b/ruby/ql/src/queries/variables/UninitializedLocal.ql index df8a275431a4..2292221240d3 100644 --- a/ruby/ql/src/queries/variables/UninitializedLocal.ql +++ b/ruby/ql/src/queries/variables/UninitializedLocal.ql @@ -18,6 +18,10 @@ class RelevantLocalVariableReadAccess extends LocalVariableReadAccess { not exists(MethodCall c | c.getReceiver() = this and c.getMethodName() = "nil?" + ) and + not exists(BinaryOperation b | + b.getLeftOperand() = this and + b.getOperator() = "||" ) } } diff --git a/ruby/ql/src/queries/variables/UnusedParameter.ql b/ruby/ql/src/queries/variables/UnusedParameter.ql index d212ee883f74..0a1ddf2a5302 100644 --- a/ruby/ql/src/queries/variables/UnusedParameter.ql +++ b/ruby/ql/src/queries/variables/UnusedParameter.ql @@ -7,6 +7,7 @@ * @id rb/unused-parameter * @tags maintainability * external/cwe/cwe-563 + * quality * @precision low */ @@ -24,5 +25,9 @@ class RelevantParameterVariable extends LocalVariable { from RelevantParameterVariable v where - not exists(Ssa::WriteDefinition def | def.getWriteAccess().getAstNode() = v.getDefiningAccess()) + not exists(Ssa::WriteDefinition def | def.getWriteAccess().getAstNode() = v.getDefiningAccess()) and + not exists(SuperCall s | s.getEnclosingCallable().getAParameter().getAVariable() = v | + // a call to 'super' without any arguments will pass on the parameter. + not exists(s.getAnArgument()) + ) select v, "The parameter '" + v.getName() + "' is never used." diff --git a/ruby/ql/test/library-tests/controlflow/graph/raise.rb b/ruby/ql/test/library-tests/controlflow/graph/raise.rb index 3caf234ab14c..0b3b3a16eac5 100644 --- a/ruby/ql/test/library-tests/controlflow/graph/raise.rb +++ b/ruby/ql/test/library-tests/controlflow/graph/raise.rb @@ -180,3 +180,25 @@ def m16(b1, b2) return 3 end end + +def m17(b1, b2) + begin + raise ExceptionA if b1 + rescue ExceptionA + if b2 + b1 = false + retry + end + end +end + +def m18(b2) + b1 = true + begin + raise ExceptionA if b1 + rescue ExceptionA + if b2 + b1 = false + end + end +end