diff --git a/ql/src/codeql_ruby/ast/Call.qll b/ql/src/codeql_ruby/ast/Call.qll index 8e5f93b4890..4953cd21348 100644 --- a/ql/src/codeql_ruby/ast/Call.qll +++ b/ql/src/codeql_ruby/ast/Call.qll @@ -2,6 +2,8 @@ private import codeql_ruby.AST private import internal.AST private import internal.Call private import internal.TreeSitter +private import codeql_ruby.dataflow.internal.DataFlowDispatch +private import codeql_ruby.dataflow.internal.DataFlowImplCommon /** * A call. @@ -49,6 +51,15 @@ class Call extends Expr, TCall { */ final int getNumberOfArguments() { result = this.(CallImpl).getNumberOfArgumentsImpl() } + /** Gets a potential target of this call, if any. */ + final Callable getATarget() { + exists(DataFlowCall c | this = c.getExpr() | + result = viableCallable(c) + or + result = viableCallableLambda(c, _) + ) + } + override AstNode getAChild(string pred) { result = super.getAChild(pred) or diff --git a/ql/test/library-tests/controlflow/graph/Cfg.expected b/ql/test/library-tests/controlflow/graph/Cfg.expected index 4595f6d5c7a..562d4cc30be 100644 --- a/ql/test/library-tests/controlflow/graph/Cfg.expected +++ b/ql/test/library-tests/controlflow/graph/Cfg.expected @@ -4061,39 +4061,39 @@ raise.rb: # 75| ensure ... #-----| -> exit m7 (normal) -# 75| [ensure: return] ensure ... -#-----| return -> exit m7 (normal) - # 75| [ensure: raise] ensure ... #-----| raise -> exit m7 (abnormal) +# 75| [ensure: return] ensure ... +#-----| return -> exit m7 (normal) + # 76| call to puts #-----| -> ensure ... -# 76| [ensure: return] call to puts -#-----| -> [ensure: return] ensure ... - # 76| [ensure: raise] call to puts #-----| -> [ensure: raise] ensure ... +# 76| [ensure: return] call to puts +#-----| -> [ensure: return] ensure ... + # 76| self #-----| -> "ensure" -# 76| [ensure: return] self -#-----| -> [ensure: return] "ensure" - # 76| [ensure: raise] self #-----| -> [ensure: raise] "ensure" +# 76| [ensure: return] self +#-----| -> [ensure: return] "ensure" + # 76| "ensure" #-----| -> call to puts -# 76| [ensure: return] "ensure" -#-----| -> [ensure: return] call to puts - # 76| [ensure: raise] "ensure" #-----| -> [ensure: raise] call to puts +# 76| [ensure: return] "ensure" +#-----| -> [ensure: return] call to puts + # 79| enter m8 #-----| -> x @@ -4173,39 +4173,39 @@ raise.rb: # 88| ensure ... #-----| -> self -# 88| [ensure: return] ensure ... -#-----| return -> exit m8 (normal) - # 88| [ensure: raise] ensure ... #-----| raise -> exit m8 (abnormal) +# 88| [ensure: return] ensure ... +#-----| return -> exit m8 (normal) + # 89| call to puts #-----| -> ensure ... -# 89| [ensure: return] call to puts -#-----| -> [ensure: return] ensure ... - # 89| [ensure: raise] call to puts #-----| -> [ensure: raise] ensure ... +# 89| [ensure: return] call to puts +#-----| -> [ensure: return] ensure ... + # 89| self #-----| -> "ensure" -# 89| [ensure: return] self -#-----| -> [ensure: return] "ensure" - # 89| [ensure: raise] self #-----| -> [ensure: raise] "ensure" +# 89| [ensure: return] self +#-----| -> [ensure: return] "ensure" + # 89| "ensure" #-----| -> call to puts -# 89| [ensure: return] "ensure" -#-----| -> [ensure: return] call to puts - # 89| [ensure: raise] "ensure" #-----| -> [ensure: raise] call to puts +# 89| [ensure: return] "ensure" +#-----| -> [ensure: return] call to puts + # 91| call to puts #-----| -> exit m8 (normal) @@ -4300,159 +4300,159 @@ raise.rb: # 103| ensure ... #-----| -> self -# 103| [ensure: return] ensure ... -#-----| return -> [ensure: return] self - # 103| [ensure: raise] ensure ... #-----| raise -> [ensure: raise] self +# 103| [ensure: return] ensure ... +#-----| return -> [ensure: return] self + # 104| call to puts #-----| -> b1 -# 104| [ensure: return] call to puts -#-----| -> [ensure: return] b1 - # 104| [ensure: raise] call to puts #-----| -> [ensure: raise] b1 +# 104| [ensure: return] call to puts +#-----| -> [ensure: return] b1 + # 104| self #-----| -> "outer ensure" -# 104| [ensure: return] self -#-----| -> [ensure: return] "outer ensure" - # 104| [ensure: raise] self #-----| -> [ensure: raise] "outer ensure" +# 104| [ensure: return] self +#-----| -> [ensure: return] "outer ensure" + # 104| "outer ensure" #-----| -> call to puts -# 104| [ensure: return] "outer ensure" -#-----| -> [ensure: return] call to puts - # 104| [ensure: raise] "outer ensure" #-----| -> [ensure: raise] call to puts +# 104| [ensure: return] "outer ensure" +#-----| -> [ensure: return] call to puts + # 106| if ... #-----| -> self -# 106| [ensure: return] if ... -#-----| -> [ensure: return] self - # 106| [ensure: raise] if ... #-----| -> [ensure: raise] self +# 106| [ensure: return] if ... +#-----| -> [ensure: return] self + # 106| b1 #-----| false -> if ... #-----| true -> self -# 106| [ensure: return] b1 -#-----| false -> [ensure: return] if ... -#-----| true -> [ensure: return] self - # 106| [ensure: raise] b1 #-----| false -> [ensure: raise] if ... #-----| true -> [ensure: raise] self +# 106| [ensure: return] b1 +#-----| false -> [ensure: return] if ... +#-----| true -> [ensure: return] self + # 107| call to raise #-----| raise -> [ensure(1): raise] self -# 107| [ensure: return] call to raise -#-----| raise -> [ensure: return, ensure(1): raise] self - # 107| [ensure: raise] call to raise #-----| raise -> [ensure: raise, ensure(1): raise] self +# 107| [ensure: return] call to raise +#-----| raise -> [ensure: return, ensure(1): raise] self + # 107| self #-----| -> "b1 is true" -# 107| [ensure: return] self -#-----| -> [ensure: return] "b1 is true" - # 107| [ensure: raise] self #-----| -> [ensure: raise] "b1 is true" +# 107| [ensure: return] self +#-----| -> [ensure: return] "b1 is true" + # 107| "b1 is true" #-----| -> call to raise -# 107| [ensure: return] "b1 is true" -#-----| -> [ensure: return] call to raise - # 107| [ensure: raise] "b1 is true" #-----| -> [ensure: raise] call to raise +# 107| [ensure: return] "b1 is true" +#-----| -> [ensure: return] call to raise + # 109| ensure ... #-----| -> ensure ... # 109| [ensure(1): raise] ensure ... #-----| raise -> [ensure: raise] self -# 109| [ensure: return] ensure ... -#-----| -> [ensure: return] ensure ... - -# 109| [ensure: return, ensure(1): raise] ensure ... -#-----| raise -> [ensure: raise] self - # 109| [ensure: raise] ensure ... #-----| -> [ensure: raise] ensure ... # 109| [ensure: raise, ensure(1): raise] ensure ... #-----| raise -> [ensure: raise] self +# 109| [ensure: return] ensure ... +#-----| -> [ensure: return] ensure ... + +# 109| [ensure: return, ensure(1): raise] ensure ... +#-----| raise -> [ensure: raise] self + # 110| call to puts #-----| -> ensure ... # 110| [ensure(1): raise] call to puts #-----| -> [ensure(1): raise] ensure ... -# 110| [ensure: return] call to puts -#-----| -> [ensure: return] ensure ... - -# 110| [ensure: return, ensure(1): raise] call to puts -#-----| -> [ensure: return, ensure(1): raise] ensure ... - # 110| [ensure: raise] call to puts #-----| -> [ensure: raise] ensure ... # 110| [ensure: raise, ensure(1): raise] call to puts #-----| -> [ensure: raise, ensure(1): raise] ensure ... +# 110| [ensure: return] call to puts +#-----| -> [ensure: return] ensure ... + +# 110| [ensure: return, ensure(1): raise] call to puts +#-----| -> [ensure: return, ensure(1): raise] ensure ... + # 110| self #-----| -> "inner ensure" # 110| [ensure(1): raise] self #-----| -> [ensure(1): raise] "inner ensure" -# 110| [ensure: return] self -#-----| -> [ensure: return] "inner ensure" - -# 110| [ensure: return, ensure(1): raise] self -#-----| -> [ensure: return, ensure(1): raise] "inner ensure" - # 110| [ensure: raise] self #-----| -> [ensure: raise] "inner ensure" # 110| [ensure: raise, ensure(1): raise] self #-----| -> [ensure: raise, ensure(1): raise] "inner ensure" +# 110| [ensure: return] self +#-----| -> [ensure: return] "inner ensure" + +# 110| [ensure: return, ensure(1): raise] self +#-----| -> [ensure: return, ensure(1): raise] "inner ensure" + # 110| "inner ensure" #-----| -> call to puts # 110| [ensure(1): raise] "inner ensure" #-----| -> [ensure(1): raise] call to puts -# 110| [ensure: return] "inner ensure" -#-----| -> [ensure: return] call to puts - -# 110| [ensure: return, ensure(1): raise] "inner ensure" -#-----| -> [ensure: return, ensure(1): raise] call to puts - # 110| [ensure: raise] "inner ensure" #-----| -> [ensure: raise] call to puts # 110| [ensure: raise, ensure(1): raise] "inner ensure" #-----| -> [ensure: raise, ensure(1): raise] call to puts +# 110| [ensure: return] "inner ensure" +#-----| -> [ensure: return] call to puts + +# 110| [ensure: return, ensure(1): raise] "inner ensure" +#-----| -> [ensure: return, ensure(1): raise] call to puts + # 113| call to puts #-----| -> self @@ -4465,87 +4465,87 @@ raise.rb: # 114| ensure ... #-----| -> exit m9 (normal) -# 114| [ensure: return] ensure ... -#-----| return -> exit m9 (normal) - # 114| [ensure: raise] ensure ... #-----| raise -> exit m9 (abnormal) +# 114| [ensure: return] ensure ... +#-----| return -> exit m9 (normal) + # 115| call to puts #-----| -> b2 -# 115| [ensure: return] call to puts -#-----| -> [ensure: return] b2 - # 115| [ensure: raise] call to puts #-----| -> [ensure: raise] b2 +# 115| [ensure: return] call to puts +#-----| -> [ensure: return] b2 + # 115| self #-----| -> "method ensure" -# 115| [ensure: return] self -#-----| -> [ensure: return] "method ensure" - # 115| [ensure: raise] self #-----| -> [ensure: raise] "method ensure" +# 115| [ensure: return] self +#-----| -> [ensure: return] "method ensure" + # 115| "method ensure" #-----| -> call to puts -# 115| [ensure: return] "method ensure" -#-----| -> [ensure: return] call to puts - # 115| [ensure: raise] "method ensure" #-----| -> [ensure: raise] call to puts +# 115| [ensure: return] "method ensure" +#-----| -> [ensure: return] call to puts + # 116| if ... #-----| -> ensure ... -# 116| [ensure: return] if ... -#-----| -> [ensure: return] ensure ... - # 116| [ensure: raise] if ... #-----| -> [ensure: raise] ensure ... +# 116| [ensure: return] if ... +#-----| -> [ensure: return] ensure ... + # 116| b2 #-----| false -> if ... #-----| true -> self -# 116| [ensure: return] b2 -#-----| false -> [ensure: return] if ... -#-----| true -> [ensure: return] self - # 116| [ensure: raise] b2 #-----| false -> [ensure: raise] if ... #-----| true -> [ensure: raise] self -# 117| call to raise -#-----| raise -> exit m9 (abnormal) +# 116| [ensure: return] b2 +#-----| false -> [ensure: return] if ... +#-----| true -> [ensure: return] self -# 117| [ensure: return] call to raise +# 117| call to raise #-----| raise -> exit m9 (abnormal) # 117| [ensure: raise] call to raise #-----| raise -> exit m9 (abnormal) +# 117| [ensure: return] call to raise +#-----| raise -> exit m9 (abnormal) + # 117| self #-----| -> "b2 is true" -# 117| [ensure: return] self -#-----| -> [ensure: return] "b2 is true" - # 117| [ensure: raise] self #-----| -> [ensure: raise] "b2 is true" +# 117| [ensure: return] self +#-----| -> [ensure: return] "b2 is true" + # 117| "b2 is true" #-----| -> call to raise -# 117| [ensure: return] "b2 is true" -#-----| -> [ensure: return] call to raise - # 117| [ensure: raise] "b2 is true" #-----| -> [ensure: raise] call to raise +# 117| [ensure: return] "b2 is true" +#-----| -> [ensure: return] call to raise + # 121| enter m10 #-----| -> p diff --git a/ql/test/library-tests/modules/callgraph.ql b/ql/test/library-tests/modules/callgraph.ql index 5dac6d2ccbd..5710b9a3324 100644 --- a/ql/test/library-tests/modules/callgraph.ql +++ b/ql/test/library-tests/modules/callgraph.ql @@ -1,6 +1,5 @@ import ruby -import codeql_ruby.dataflow.internal.DataFlowDispatch -query DataFlowCallable getTarget(DataFlowCall call) { result = call.getTarget() } +query Callable getTarget(Call call) { result = call.getATarget() } -query predicate unresolvedCall(DataFlowCall call) { not exists(call.getTarget()) } +query predicate unresolvedCall(Call call) { not exists(call.getATarget()) }