Skip to content

Commit c57b7c5

Browse files
committed
Data flow: Restrict ExprReturnNode to nodes from the body of the callable
1 parent 397b834 commit c57b7c5

File tree

3 files changed

+21
-8
lines changed

3 files changed

+21
-8
lines changed

ruby/ql/lib/codeql/ruby/ast/Method.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ private import internal.AST
44
private import internal.TreeSitter
55

66
/** A callable. */
7-
class Callable extends Expr, Scope, TCallable {
7+
class Callable extends StmtSequence, Expr, Scope, TCallable {
88
/** Gets the number of parameters of this callable. */
99
final int getNumberOfParameters() { result = count(this.getAParameter()) }
1010

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

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -514,8 +514,8 @@ private module ReturnNodes {
514514
}
515515

516516
/**
517-
* A data-flow node that represents an expression returned by a callable,
518-
* either using an explict `return` statement or as the expression of a method body.
517+
* A data-flow node that represents an expression explicitly returned by
518+
* a callable.
519519
*/
520520
class ExplicitReturnNode extends ReturningNode, ReturningStatementNode {
521521
ExplicitReturnNode() {
@@ -531,11 +531,25 @@ private module ReturnNodes {
531531
}
532532
}
533533

534+
pragma[noinline]
535+
private AstNode implicitReturn(Callable c, ExprNode n) {
536+
exists(CfgNodes::ExprCfgNode en |
537+
en = n.getExprNode() and
538+
en.getASuccessor().(CfgNodes::AnnotatedExitNode).isNormal() and
539+
n.(NodeImpl).getCfgScope() = c and
540+
result = en.getExpr()
541+
)
542+
or
543+
result = implicitReturn(c, n).getParent()
544+
}
545+
546+
/**
547+
* A data-flow node that represents an expression implicitly returned by
548+
* a callable. An implicit return happens when an expression can be the
549+
* last thing that is evaluated in the body of the callable.
550+
*/
534551
class ExprReturnNode extends ReturningNode, ExprNode {
535-
ExprReturnNode() {
536-
this.getExprNode().getASuccessor().(CfgNodes::AnnotatedExitNode).isNormal() and
537-
this.(NodeImpl).getCfgScope() instanceof Callable
538-
}
552+
ExprReturnNode() { exists(Callable c | implicitReturn(c, this) = c.getAStmt()) }
539553

540554
override ReturnKind getKind() { result instanceof NormalReturnKind }
541555
}

ruby/ql/test/library-tests/dataflow/local/Nodes.expected

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ ret
88
| local_dataflow.rb:50:3:50:13 | next |
99
| local_dataflow.rb:51:3:51:15 | break |
1010
| local_dataflow.rb:52:3:52:10 | "normal" |
11-
| local_dataflow.rb:57:9:57:9 | x |
1211
arg
1312
| local_dataflow.rb:3:8:3:10 | self | local_dataflow.rb:3:8:3:10 | call to p | -1 |
1413
| local_dataflow.rb:3:10:3:10 | a | local_dataflow.rb:3:8:3:10 | call to p | 0 |

0 commit comments

Comments
 (0)