Skip to content

Commit 4aec6bd

Browse files
committed
Ruby: Fix ExprReturnNode to handle Rescue, Ensure, and Else.
1 parent 0751408 commit 4aec6bd

1 file changed

Lines changed: 18 additions & 10 deletions

File tree

ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,16 +1643,24 @@ private module ReturnNodes {
16431643
}
16441644
}
16451645

1646-
pragma[noinline]
1647-
private AstNode implicitReturn(Callable c, ExprNode n) {
1648-
exists(CfgNodes::ExprCfgNode en |
1649-
en = n.getExprNode() and
1650-
en.getASuccessor().(CfgNodes::AnnotatedExitNode).isNormal() and
1651-
n.(NodeImpl).getCfgScope() = c and
1652-
result = en.getExpr()
1653-
)
1646+
private AstNode desugar(AstNode n) {
1647+
result = n.getDesugared()
1648+
or
1649+
not exists(n.getDesugared()) and
1650+
result = n
1651+
}
1652+
1653+
private Expr getLast(StmtSequence s) {
1654+
result = getLast(s.(BodyStmt).getElse())
16541655
or
1655-
result = implicitReturn(c, n).getParent()
1656+
result = getLast(s.(BodyStmt).getARescue().getBody())
1657+
or
1658+
not exists(s.(BodyStmt).getElse()) and
1659+
exists(Stmt last | last = s.getLastStmt() |
1660+
result = getLast(last)
1661+
or
1662+
result = last and not last instanceof StmtSequence
1663+
)
16561664
}
16571665

16581666
/**
@@ -1661,7 +1669,7 @@ private module ReturnNodes {
16611669
* last thing that is evaluated in the body of the callable.
16621670
*/
16631671
class ExprReturnNode extends SourceReturnNode, ExprNode {
1664-
ExprReturnNode() { exists(Callable c | implicitReturn(c, this) = c.getBody().getAStmt()) }
1672+
ExprReturnNode() { this.getExprNode().getExpr() = desugar(getLast(any(Callable c).getBody())) }
16651673

16661674
override ReturnKind getKindSource() {
16671675
exists(CfgScope scope | scope = this.(NodeImpl).getCfgScope() |

0 commit comments

Comments
 (0)