diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowDispatch.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowDispatch.qll index ea768f547153..581f049ab316 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowDispatch.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowDispatch.qll @@ -149,9 +149,10 @@ predicate golangSpecificParamArgFilter( // Interface methods calls may be passed strictly to that exact method's model receiver: arg.getPosition() != -1 or - exists(Function callTarget | callTarget = call.getNode().(DataFlow::CallNode).getTarget() | - not isInterfaceMethod(callTarget) - or - callTarget = p.getCallable().asSummarizedCallable().asFunction() - ) + p instanceof DataFlow::SummarizedParameterNode + or + not isInterfaceMethod(call.getNode() + .(DataFlow::CallNode) + .getACalleeWithoutVirtualDispatch() + .asFunction()) } diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll index 59224024ec34..5a51f16b83ad 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll @@ -489,13 +489,9 @@ module Public { * interface type. */ Callable getACalleeIncludingExternals() { - result.asFunction() = this.getTarget() + result = this.getACalleeWithoutVirtualDispatch() or exists(DataFlow::Node calleeSource | calleeSource = this.getACalleeSource() | - result.asFuncLit() = calleeSource.asExpr() - or - calleeSource = result.asFunction().getARead() - or exists(Method declared, Method actual | calleeSource = declared.getARead() and actual.implements(declared) and @@ -510,6 +506,19 @@ module Public { */ FuncDef getACallee() { result = this.getACalleeIncludingExternals().getFuncDef() } + /** + * Gets the definition of a possible target of this call, excluding targets reachable via virtual dispatch. + */ + Callable getACalleeWithoutVirtualDispatch() { + result.asFunction() = this.getTarget() + or + exists(DataFlow::Node calleeSource | calleeSource = this.getACalleeSource() | + result.asFuncLit() = calleeSource.asExpr() + or + calleeSource = result.asFunction().getARead() + ) + } + /** * Gets the name of the function, method or variable that is being called. *