Skip to content

Commit 1e3d818

Browse files
committed
Update CallNode.getArgument for implicit varargs
It now has one only result corresponding to a variadic parameter. If the argument is followed by an ellipsis then it is just the argument itself. Otherwise it is a ImplicitVarargsSlice node.
1 parent 3e73e02 commit 1e3d818

File tree

1 file changed

+54
-9
lines changed

1 file changed

+54
-9
lines changed

go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -534,16 +534,11 @@ module Public {
534534
CallExpr getCall() { result = this.getExpr() }
535535

536536
/**
537-
* Gets the data flow node corresponding to the `i`th argument of this call.
538-
*
539-
* Note that the first argument in calls to the built-in function `make` is a type, which is
540-
* not a data-flow node. It is skipped for the purposes of this predicate, so the (syntactically)
541-
* second argument becomes the first argument in terms of data flow.
542-
*
543-
* For calls of the form `f(g())` where `g` has multiple results, the arguments of the call to
544-
* `i` are the (implicit) element extraction nodes for the call to `g`.
537+
* Gets the `i`th argument of this call, where tuple extraction has been
538+
* done but arguments corresponding to a variadic parameter are still
539+
* considered separate.
545540
*/
546-
Node getArgument(int i) {
541+
Node getSyntacticArgument(int i) {
547542
if expr.getArgument(0).getType() instanceof TupleType
548543
then result = DataFlow::extractTupleElement(DataFlow::exprNode(expr.getArgument(0)), i)
549544
else
@@ -555,12 +550,62 @@ module Public {
555550
)
556551
}
557552

553+
/**
554+
* Gets the data flow node corresponding to an argument of this call, where
555+
* tuple extraction has been done but arguments corresponding to a variadic
556+
* parameter are still considered separate.
557+
*/
558+
Node getASyntacticArgument() { result = this.getSyntacticArgument(_) }
559+
560+
/**
561+
* Gets the data flow node corresponding to the `i`th argument of this call.
562+
*
563+
* Note that the first argument in calls to the built-in function `make` is a type, which is
564+
* not a data-flow node. It is skipped for the purposes of this predicate, so the (syntactically)
565+
* second argument becomes the first argument in terms of data flow.
566+
*
567+
* For calls of the form `f(g())` where `g` has multiple results, the arguments of the call to
568+
* `i` are the (implicit) element extraction nodes for the call to `g`.
569+
*
570+
* For calls to variadic functions without an ellipsis (`...`), there is a single argument of type
571+
* `ImplicitVarargsSlice` corresponding to the variadic parameter. This is in contrast to the member
572+
* predicate `getArgument` on `CallExpr`, which gets the syntactic arguments.
573+
*/
574+
Node getArgument(int i) {
575+
exists(SignatureType t, int lastParamIndex |
576+
t = this.getACalleeIncludingExternals().getType() and
577+
lastParamIndex = t.getNumParameter() - 1
578+
|
579+
if
580+
not this.hasEllipsis() and
581+
t.isVariadic() and
582+
i >= lastParamIndex
583+
then
584+
result.(ImplicitVarargsSlice).getCallNode() = this and
585+
i = lastParamIndex
586+
else result = this.getSyntacticArgument(i)
587+
)
588+
}
589+
558590
/** Gets the data flow node corresponding to an argument of this call. */
559591
Node getAnArgument() { result = this.getArgument(_) }
560592

561593
/** Gets the number of arguments of this call, if it can be determined. */
562594
int getNumArgument() { result = count(this.getAnArgument()) }
563595

596+
/**
597+
* Gets the 'i'th argument without an ellipsis after it which is passed to
598+
* the varargs parameter of the target of this call (if there is one).
599+
*/
600+
Node getImplicitVarargsArgument(int i) {
601+
not this.hasEllipsis() and
602+
i >= 0 and
603+
exists(Function f | f = this.getTarget() |
604+
f.isVariadic() and
605+
result = this.getSyntacticArgument(f.getNumParameter() - 1 + i)
606+
)
607+
}
608+
564609
/** Gets a function passed as the `i`th argument of this call. */
565610
FunctionNode getCallback(int i) { result.getASuccessor*() = this.getArgument(i) }
566611

0 commit comments

Comments
 (0)