Skip to content
This repository was archived by the owner on Jan 5, 2023. It is now read-only.

Commit d31b4d2

Browse files
authored
Merge pull request #281 from max-schaefer/has_ellipsis
Teach extractor to distinguish calls with an ellipsis from calls without
2 parents 97291e4 + 2ef4212 commit d31b4d2

File tree

22 files changed

+988
-6
lines changed

22 files changed

+988
-6
lines changed

extractor/dbscheme/tables.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,3 +951,7 @@ var ErrorsTable = NewTable("errors",
951951
EntityColumn(PackageType, "package"),
952952
IntColumn("idx"),
953953
).KeySet("package", "idx")
954+
955+
var HasEllipsisTable = NewTable("has_ellipsis",
956+
EntityColumn(CallOrConversionExpr, "id"),
957+
)

extractor/extractor.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,9 @@ func extractExpr(tw *trap.Writer, expr ast.Expr, parent trap.Label, idx int) {
716716
kind = dbscheme.CallOrConversionExpr.Index()
717717
extractExpr(tw, expr.Fun, lbl, 0)
718718
extractExprs(tw, expr.Args, lbl, 1, 1)
719+
if expr.Ellipsis.IsValid() {
720+
dbscheme.HasEllipsisTable.Emit(tw, lbl)
721+
}
719722
case *ast.StarExpr:
720723
if expr == nil {
721724
return

ql/src/go.dbscheme

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ modtokens(string token: string ref, int parent: @modexpr ref, int idx: int ref);
129129
errors(unique int id: @error, int kind: int ref, string msg: string ref, string rawpos: string ref,
130130
string file: string ref, int line: int ref, int col: int ref, int package: @package ref, int idx: int ref);
131131

132+
has_ellipsis(int id: @callorconversionexpr ref);
133+
132134
@container = @file | @folder;
133135

134136
@locatable = @node | @localscope;

ql/src/go.dbscheme.stats

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4114,7 +4114,7 @@
41144114
<b>
41154115
<a>1</a>
41164116
<b>2</b>
4117-
<v>49</v>
4117+
<v>47</v>
41184118
</b>
41194119
<b>
41204120
<a>2</a>
@@ -4124,7 +4124,7 @@
41244124
<b>
41254125
<a>3</a>
41264126
<b>4</b>
4127-
<v>32</v>
4127+
<v>33</v>
41284128
</b>
41294129
<b>
41304130
<a>4</a>
@@ -4134,7 +4134,7 @@
41344134
<b>
41354135
<a>5</a>
41364136
<b>7</b>
4137-
<v>38</v>
4137+
<v>39</v>
41384138
</b>
41394139
<b>
41404140
<a>7</a>
@@ -4219,7 +4219,7 @@
42194219
</b>
42204220
<b>
42214221
<a>323</a>
4222-
<b>521</b>
4222+
<b>515</b>
42234223
<v>7</v>
42244224
</b>
42254225
</bs>
@@ -10926,5 +10926,16 @@
1092610926
</dep>
1092710927
</dependencies>
1092810928
</relation>
10929+
<relation>
10930+
<name>has_ellipsis</name>
10931+
<cardinality>268</cardinality>
10932+
<columnsizes>
10933+
<e>
10934+
<k>id</k>
10935+
<v>268</v>
10936+
</e>
10937+
</columnsizes>
10938+
<dependencies/>
10939+
</relation>
1092910940
</stats>
1093010941
</dbstats>

ql/src/semmle/go/Expr.qll

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,12 @@ class ConversionExpr extends CallOrConversionExpr {
726726
* ```
727727
*/
728728
class CallExpr extends CallOrConversionExpr {
729-
CallExpr() { exists(Expr callee | callee = getChildExpr(0) | not isTypeExprBottomUp(callee)) }
729+
CallExpr() {
730+
exists(Expr callee | callee = getChildExpr(0) | not isTypeExprBottomUp(callee))
731+
or
732+
// only calls can have an ellipsis after their last argument
733+
has_ellipsis(this)
734+
}
730735

731736
/** Gets the expression representing the function being called. */
732737
Expr getCalleeExpr() { result = getChildExpr(0) }
@@ -755,6 +760,9 @@ class CallExpr extends CallOrConversionExpr {
755760
/** Gets the declared target of this call. */
756761
Function getTarget() { getCalleeExpr() = result.getAReference() }
757762

763+
/** Holds if this call has an ellipsis after its last argument. */
764+
predicate hasEllipsis() { has_ellipsis(this) }
765+
758766
override predicate mayHaveOwnSideEffects() {
759767
getTarget().mayHaveSideEffects() or
760768
not exists(getTarget())

ql/src/semmle/go/dataflow/FunctionInputsAndOutputs.qll

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,12 @@ private class OutReceiver extends FunctionOutput, TOutReceiver {
242242
override string toString() { result = "receiver" }
243243
}
244244

245-
/** A parameter of a function, viewed as an output. */
245+
/**
246+
* A parameter of a function, viewed as an output.
247+
*
248+
* Note that slices passed to varargs parameters using `...` are not included, since in this
249+
* case it is ambiguous whether the output should be the slice itself or one of its elements.
250+
*/
246251
private class OutParameter extends FunctionOutput, TOutParameter {
247252
int index;
248253

@@ -259,6 +264,9 @@ private class OutParameter extends FunctionOutput, TOutParameter {
259264
override DataFlow::Node getExitNode(DataFlow::CallNode c) {
260265
exists(DataFlow::Node arg |
261266
arg = getArgument(c, index) and
267+
// exclude slices passed to varargs parameters using `...` calls
268+
not (c.hasEllipsis() and index = c.getNumArgument() - 1)
269+
|
262270
result.(DataFlow::PostUpdateNode).getPreUpdateNode() = arg
263271
)
264272
}

ql/src/semmle/go/dataflow/internal/DataFlowUtil.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,9 @@ class CallNode extends ExprNode {
377377

378378
/** Gets the data flow node corresponding to the receiver of this call, if any. */
379379
Node getReceiver() { result = getACalleeSource().(MethodReadNode).getReceiver() }
380+
381+
/** Holds if this call has an ellipsis after its last argument. */
382+
predicate hasEllipsis() { expr.hasEllipsis() }
380383
}
381384

382385
/** A data flow node that represents a call to a method. */

ql/test/library-tests/semmle/go/Expr/BasicLit_getText.expected

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@
2626
| consts.go:46:16:46:16 | 2 | 2 |
2727
| consts.go:47:16:47:18 | 1.0 | 1.0 |
2828
| consts.go:48:16:48:19 | "hi" | "hi" |
29+
| ellipsis.go:7:4:7:4 | 1 | 1 |
30+
| ellipsis.go:8:4:8:4 | 1 | 1 |
31+
| ellipsis.go:8:7:8:7 | 2 | 2 |
32+
| ellipsis.go:9:4:9:4 | 1 | 1 |
33+
| ellipsis.go:9:7:9:7 | 2 | 2 |
34+
| ellipsis.go:9:10:9:10 | 3 | 3 |
35+
| ellipsis.go:10:4:10:4 | 1 | 1 |
36+
| ellipsis.go:10:13:10:13 | 2 | 2 |
37+
| ellipsis.go:10:16:10:16 | 3 | 3 |
2938
| literals.go:3:8:3:12 | "fmt" | "fmt" |
3039
| literals.go:8:2:8:10 | "decimal" | "decimal" |
3140
| literals.go:8:17:8:18 | 42 | 42 |

ql/test/library-tests/semmle/go/Expr/BasicLit_getValue.expected

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@
2626
| consts.go:46:16:46:16 | 2 | 2 |
2727
| consts.go:47:16:47:18 | 1.0 | 1.0 |
2828
| consts.go:48:16:48:19 | "hi" | hi |
29+
| ellipsis.go:7:4:7:4 | 1 | 1 |
30+
| ellipsis.go:8:4:8:4 | 1 | 1 |
31+
| ellipsis.go:8:7:8:7 | 2 | 2 |
32+
| ellipsis.go:9:4:9:4 | 1 | 1 |
33+
| ellipsis.go:9:7:9:7 | 2 | 2 |
34+
| ellipsis.go:9:10:9:10 | 3 | 3 |
35+
| ellipsis.go:10:4:10:4 | 1 | 1 |
36+
| ellipsis.go:10:13:10:13 | 2 | 2 |
37+
| ellipsis.go:10:16:10:16 | 3 | 3 |
2938
| literals.go:3:8:3:12 | "fmt" | fmt |
3039
| literals.go:8:2:8:10 | "decimal" | decimal |
3140
| literals.go:8:17:8:18 | 42 | 42 |

ql/test/library-tests/semmle/go/Expr/CompositeLit.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
| ellipsis.go:10:7:10:17 | composite literal | 0 | value | ellipsis.go:10:13:10:13 | 2 |
2+
| ellipsis.go:10:7:10:17 | composite literal | 1 | value | ellipsis.go:10:16:10:16 | 3 |
13
| literals.go:7:15:11:1 | map literal | 0 | key | literals.go:8:2:8:10 | "decimal" |
24
| literals.go:7:15:11:1 | map literal | 0 | value | literals.go:8:17:8:18 | 42 |
35
| literals.go:7:15:11:1 | map literal | 1 | key | literals.go:9:2:9:8 | "octal" |

0 commit comments

Comments
 (0)