diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll index 5a3c589197e..73f3f35fbb0 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll @@ -480,7 +480,11 @@ module Public { class CallNode extends ExprNode { override CallExpr expr; - /** Gets the declared target of this call */ + /** + * Gets the declared target of this call, if it exists. + * + * This doesn't exist when a function is called via a variable. + */ Function getTarget() { result = expr.getTarget() } private DataFlow::Node getACalleeSource() { result = getACalleeSource(this) } @@ -637,14 +641,41 @@ module Public { /** Gets a result of this call. */ Node getAResult() { result = this.getResult(_) } - /** Gets the data flow node corresponding to the receiver of this call, if any. */ + /** + * Gets the data flow node corresponding to the receiver of this call, if any. + * + * When a method value is assigned to a variable then when it is called it + * looks like a function call, as in the following example. + * + * ```go + * file, _ := os.Open("test.txt") + * f := file.Close + * f() + * ``` + * + * In this case we use local flow to try to find the receiver (`file` in + * the above example). + */ Node getReceiver() { result = this.getACalleeSource().(MethodReadNode).getReceiver() } /** Holds if this call has an ellipsis after its last argument. */ predicate hasEllipsis() { expr.hasEllipsis() } } - /** A data flow node that represents a call to a method. */ + /** + * A data flow node that represents a direct call to a method. + * + * When a method value is assigned to a variable then when it is called it + * syntactically looks like a function call, as in the following example. + * + * ```go + * file, _ := os.Open("test.txt") + * f := file.Close + * f() + * ``` + * + * In this case it will not be considered a `MethodCallNode`. + */ class MethodCallNode extends CallNode { MethodCallNode() { expr.getTarget() instanceof Method }