Skip to content

Commit d46cf03

Browse files
committed
Distinguish interface from concrete method receivers.
Golang's historical approach has been that specifically receiver arguments are not tracked across virtual (interface) dispatch (ordinary arguments are), but models of interface methods do apply both to the receiver and ordinary arguments. Here I approach that problem by introducing two distinct argument/parameter positions, -1 (ordinary receiver) and -2 (interface receiver). The receiver is passed in ordinary receiver position (-1) if the call is non-virtual, resulting in flow to whatever concrete method is called and perhaps a SummarizedCallable model too, while it is passed in interface receiver position in the case of a virtual call, perhaps matching the interface receiver of a SummarizedCallable model (it cannot match a concrete method, since the interface method does not have a body).
1 parent 2f10f21 commit d46cf03

File tree

5 files changed

+97
-58
lines changed

5 files changed

+97
-58
lines changed

go/ql/lib/semmle/go/dataflow/ExternalFlow.qll

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -295,15 +295,6 @@ SourceOrSinkElement interpretElement(
295295
)
296296
}
297297

298-
/** Holds if there is an external specification for `f`. */
299-
predicate hasExternalSpecification(Function f) {
300-
f = any(SummarizedCallable sc).asFunction()
301-
or
302-
exists(SourceOrSinkElement e | f = e.asEntity() |
303-
sourceElement(e, _, _, _) or sinkElement(e, _, _, _)
304-
)
305-
}
306-
307298
private predicate parseField(AccessPathToken c, DataFlow::FieldContent f) {
308299
exists(string fieldRegex, string package, string className, string fieldName |
309300
fieldRegex = "^Field\\[(.*)\\.([^.]+)\\.([^.]+)\\]$" and

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ predicate mayBenefitFromCallContext(DataFlowCall call, DataFlowCallable f) { non
117117
DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) { none() }
118118

119119
private int parameterPosition() {
120-
result = [-1 .. any(DataFlowCallable c).getType().getNumParameter()]
120+
result = [-2 .. any(DataFlowCallable c).getType().getNumParameter()]
121121
}
122122

123123
/** A parameter position represented by an integer. */

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

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,38 @@ private import DataFlowPrivate
55
private import FlowSummaryImpl as FlowSummaryImpl
66
private import semmle.go.dataflow.ExternalFlow
77

8+
private predicate isInterfaceMethod(Method c) {
9+
c.getReceiverBaseType().getUnderlyingType() instanceof InterfaceType
10+
}
11+
12+
private SummaryComponent stateBottom(FlowSummaryImpl::Private::SummaryNodeState state) {
13+
exists(SummaryComponentStack stack |
14+
state.isInputState(_, stack) or
15+
state.isOutputState(_, stack)
16+
|
17+
result = stack.bottom()
18+
)
19+
}
20+
821
cached
922
private newtype TNode =
1023
MkInstructionNode(IR::Instruction insn) or
1124
MkSsaNode(SsaDefinition ssa) or
1225
MkGlobalFunctionNode(Function f) or
1326
MkSummarizedParameterNode(SummarizedCallable c, int i) {
14-
FlowSummaryImpl::Private::summaryParameterNodeRange(c, i)
27+
FlowSummaryImpl::Private::summaryParameterNodeRange(c, i) and
28+
if isInterfaceMethod(c.asFunction()) then i != -1 else i != -2
1529
} or
1630
MkSummaryInternalNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
17-
FlowSummaryImpl::Private::summaryNodeRange(c, state)
31+
FlowSummaryImpl::Private::summaryNodeRange(c, state) and
32+
if isInterfaceMethod(c.asFunction())
33+
then (
34+
stateBottom(state) != SummaryComponent::parameter(-1) and
35+
stateBottom(state) != SummaryComponent::argument(-1)
36+
) else (
37+
stateBottom(state) != SummaryComponent::parameter(-2) and
38+
stateBottom(state) != SummaryComponent::argument(-2)
39+
)
1840
}
1941

2042
/** Nodes intended for only use inside the data-flow libraries. */
@@ -34,14 +56,36 @@ module Private {
3456
n = MkSummaryInternalNode(result.asSummarizedCallable(), _)
3557
}
3658

37-
/** Holds if `p` is a `ParameterNode` of `c` with position `pos`. */
59+
/**
60+
* Holds if `p` is a `ParameterNode` of `c` with position `pos`.
61+
*
62+
* Note that we renumber the receiver of an interface method to -2 instead of the
63+
* usual -1, in order to only propagate flow from the receiver of interface method calls
64+
* to interface methods themselves (which are necessarily models), rather than to
65+
* concrete methods implementing the interface, as is done for regular parameters.
66+
*/
3867
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) {
39-
p.isParameterOf(c, pos)
68+
exists(int realPos | p.isParameterOf(c, realPos) |
69+
if realPos = -1 and isInterfaceMethod(c.asSummarizedCallable().asFunction())
70+
then pos = -2
71+
else realPos = pos
72+
)
4073
}
4174

42-
/** Holds if `arg` is an `ArgumentNode` of `c` with position `pos`. */
75+
/**
76+
* Holds if `arg` is an `ArgumentNode` of `c` with position `pos`.
77+
*
78+
* Note that we renumber the receiver of an interface call to -2 instead of the
79+
* usual -1, in order to only propagate flow from the receiver of interface method calls
80+
* to interface methods themselves (which are necessarily models), rather than to
81+
* concrete methods implementing the interface, as is done for regular parameters.
82+
*/
4383
predicate isArgumentNode(ArgumentNode arg, DataFlowCall c, ArgumentPosition pos) {
44-
arg.argumentOf(c, pos)
84+
exists(int realPos | arg.argumentOf(c, realPos) |
85+
if realPos = -1 and isInterfaceMethod(c.getNode().(DataFlow::CallNode).getTarget())
86+
then pos = -2
87+
else realPos = pos
88+
)
4589
}
4690

4791
/** A data flow node that represents returning a value from a function. */
@@ -718,20 +762,8 @@ module Public {
718762
* Holds if this argument occurs at the given position in the given call.
719763
*
720764
* The receiver argument is considered to have index `-1`.
721-
*
722-
* Note that we currently do not track receiver arguments into calls to interface methods.
723765
*/
724-
predicate argumentOf(CallExpr call, int pos) {
725-
call = c.asExpr() and
726-
pos = i and
727-
(
728-
i != -1
729-
or
730-
exists(c.(MethodCallNode).getTarget().getBody())
731-
or
732-
hasExternalSpecification(c.(DataFlow::MethodCallNode).getTarget())
733-
)
734-
}
766+
predicate argumentOf(CallExpr call, int pos) { call = c.asExpr() and pos = i }
735767

736768
/**
737769
* Gets the `CallNode` this is an argument to.

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

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,10 +272,26 @@ private int parseConstantOrRange(string arg) {
272272
)
273273
}
274274

275+
/**
276+
* Gets an integer specified by the integer or range `arg`, adding `-2` in the case that the result would include `-1`.
277+
*/
278+
bindingset[arg]
279+
private int parseConstantOrRangeAddingInterfaceReceiver(string arg) {
280+
exists(int written | written = parseConstantOrRange(arg) |
281+
result = written
282+
or
283+
written = -1 and result = -2
284+
)
285+
}
286+
275287
/** Gets the argument position obtained by parsing `X` in `Parameter[X]`. */
276288
bindingset[arg]
277-
ArgumentPosition parseParamBody(string arg) { result = parseConstantOrRange(arg) }
289+
ArgumentPosition parseParamBody(string arg) {
290+
result = parseConstantOrRangeAddingInterfaceReceiver(arg)
291+
}
278292

279293
/** Gets the parameter position obtained by parsing `X` in `Argument[X]`. */
280294
bindingset[arg]
281-
ParameterPosition parseArgBody(string arg) { result = parseConstantOrRange(arg) }
295+
ParameterPosition parseArgBody(string arg) {
296+
result = parseConstantOrRangeAddingInterfaceReceiver(arg)
297+
}

go/ql/test/library-tests/semmle/go/dataflow/FlowSteps/LocalTaintStep.expected

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
| file://:0:0:0:0 | parameter 0 of ReadFile | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadFile |
4747
| file://:0:0:0:0 | parameter 0 of ReadFrom | file://:0:0:0:0 | [summary] to write: argument -1 in ReadFrom |
4848
| file://:0:0:0:0 | parameter 0 of ReadFrom | file://:0:0:0:0 | [summary] to write: argument -1 in ReadFrom |
49-
| file://:0:0:0:0 | parameter 0 of ReadFrom | file://:0:0:0:0 | [summary] to write: argument -1 in ReadFrom |
49+
| file://:0:0:0:0 | parameter 0 of ReadFrom | file://:0:0:0:0 | [summary] to write: argument -2 in ReadFrom |
5050
| file://:0:0:0:0 | parameter 0 of ReadFull | file://:0:0:0:0 | [summary] to write: argument 1 in ReadFull |
5151
| file://:0:0:0:0 | parameter 0 of Repeat | file://:0:0:0:0 | [summary] to write: return (return[0]) in Repeat |
5252
| file://:0:0:0:0 | parameter 0 of Replace | file://:0:0:0:0 | [summary] to write: return (return[0]) in Replace |
@@ -114,20 +114,20 @@
114114
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
115115
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
116116
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
117-
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
118-
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
119-
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
117+
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -2 in Write |
118+
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -2 in Write |
119+
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -2 in Write |
120120
| file://:0:0:0:0 | parameter 0 of WriteAt | file://:0:0:0:0 | [summary] to write: argument -1 in WriteAt |
121121
| file://:0:0:0:0 | parameter 0 of WriteAt | file://:0:0:0:0 | [summary] to write: argument -1 in WriteAt |
122-
| file://:0:0:0:0 | parameter 0 of WriteAt | file://:0:0:0:0 | [summary] to write: argument -1 in WriteAt |
123-
| file://:0:0:0:0 | parameter 0 of WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
122+
| file://:0:0:0:0 | parameter 0 of WriteAt | file://:0:0:0:0 | [summary] to write: argument -2 in WriteAt |
124123
| file://:0:0:0:0 | parameter 0 of WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
125124
| file://:0:0:0:0 | parameter 0 of WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
126125
| file://:0:0:0:0 | parameter 0 of WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
127126
| file://:0:0:0:0 | parameter 0 of WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
128127
| file://:0:0:0:0 | parameter 0 of WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
129128
| file://:0:0:0:0 | parameter 0 of WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
130129
| file://:0:0:0:0 | parameter 0 of WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
130+
| file://:0:0:0:0 | parameter 0 of WriteString | file://:0:0:0:0 | [summary] to write: argument -2 in WriteString |
131131
| file://:0:0:0:0 | parameter 1 of AddUintptr | file://:0:0:0:0 | [summary] to write: argument 0 in AddUintptr |
132132
| file://:0:0:0:0 | parameter 1 of AddUintptr | file://:0:0:0:0 | [summary] to write: return (return[0]) in AddUintptr |
133133
| file://:0:0:0:0 | parameter 1 of AppendQuote | file://:0:0:0:0 | [summary] to write: return (return[0]) in AppendQuote |
@@ -176,15 +176,12 @@
176176
| file://:0:0:0:0 | parameter -1 of Get | file://:0:0:0:0 | [summary] to write: return (return[0]) in Get |
177177
| file://:0:0:0:0 | parameter -1 of Get | file://:0:0:0:0 | [summary] to write: return (return[0]) in Get |
178178
| file://:0:0:0:0 | parameter -1 of Glob | file://:0:0:0:0 | [summary] to write: return (return[0]) in Glob |
179-
| file://:0:0:0:0 | parameter -1 of Glob | file://:0:0:0:0 | [summary] to write: return (return[0]) in Glob |
180-
| file://:0:0:0:0 | parameter -1 of GoString | file://:0:0:0:0 | [summary] to write: return (return[0]) in GoString |
181179
| file://:0:0:0:0 | parameter -1 of GoString | file://:0:0:0:0 | [summary] to write: return (return[0]) in GoString |
182180
| file://:0:0:0:0 | parameter -1 of Hostname | file://:0:0:0:0 | [summary] to write: return (return[0]) in Hostname |
183181
| file://:0:0:0:0 | parameter -1 of Index | file://:0:0:0:0 | [summary] to write: return (return[0]) in Index |
184182
| file://:0:0:0:0 | parameter -1 of Info | file://:0:0:0:0 | [summary] to write: return (return[0]) in Info |
185183
| file://:0:0:0:0 | parameter -1 of Info | file://:0:0:0:0 | [summary] to write: return (return[0]) in Info |
186184
| file://:0:0:0:0 | parameter -1 of Info | file://:0:0:0:0 | [summary] to write: return (return[0]) in Info |
187-
| file://:0:0:0:0 | parameter -1 of Info | file://:0:0:0:0 | [summary] to write: return (return[0]) in Info |
188185
| file://:0:0:0:0 | parameter -1 of Interface | file://:0:0:0:0 | [summary] to write: return (return[0]) in Interface |
189186
| file://:0:0:0:0 | parameter -1 of InterfaceData | file://:0:0:0:0 | [summary] to write: return (return[0]) in InterfaceData |
190187
| file://:0:0:0:0 | parameter -1 of Key | file://:0:0:0:0 | [summary] to write: return (return[0]) in Key |
@@ -203,8 +200,6 @@
203200
| file://:0:0:0:0 | parameter -1 of Name | file://:0:0:0:0 | [summary] to write: return (return[0]) in Name |
204201
| file://:0:0:0:0 | parameter -1 of Name | file://:0:0:0:0 | [summary] to write: return (return[0]) in Name |
205202
| file://:0:0:0:0 | parameter -1 of Name | file://:0:0:0:0 | [summary] to write: return (return[0]) in Name |
206-
| file://:0:0:0:0 | parameter -1 of Name | file://:0:0:0:0 | [summary] to write: return (return[0]) in Name |
207-
| file://:0:0:0:0 | parameter -1 of Open | file://:0:0:0:0 | [summary] to write: return (return[0]) in Open |
208203
| file://:0:0:0:0 | parameter -1 of Open | file://:0:0:0:0 | [summary] to write: return (return[0]) in Open |
209204
| file://:0:0:0:0 | parameter -1 of Open | file://:0:0:0:0 | [summary] to write: return (return[0]) in Open |
210205
| file://:0:0:0:0 | parameter -1 of Parse | file://:0:0:0:0 | [summary] to write: return (return[0]) in Parse |
@@ -224,17 +219,10 @@
224219
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
225220
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
226221
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
227-
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
228-
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
229-
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
230-
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
231-
| file://:0:0:0:0 | parameter -1 of ReadAt | file://:0:0:0:0 | [summary] to write: argument 0 in ReadAt |
232222
| file://:0:0:0:0 | parameter -1 of ReadAt | file://:0:0:0:0 | [summary] to write: argument 0 in ReadAt |
233223
| file://:0:0:0:0 | parameter -1 of ReadAt | file://:0:0:0:0 | [summary] to write: argument 0 in ReadAt |
234224
| file://:0:0:0:0 | parameter -1 of ReadAt | file://:0:0:0:0 | [summary] to write: argument 0 in ReadAt |
235225
| file://:0:0:0:0 | parameter -1 of ReadDir | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadDir |
236-
| file://:0:0:0:0 | parameter -1 of ReadDir | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadDir |
237-
| file://:0:0:0:0 | parameter -1 of ReadFile | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadFile |
238226
| file://:0:0:0:0 | parameter -1 of ReadFile | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadFile |
239227
| file://:0:0:0:0 | parameter -1 of Recv | file://:0:0:0:0 | [summary] to write: return (return[0]) in Recv |
240228
| file://:0:0:0:0 | parameter -1 of RequestURI | file://:0:0:0:0 | [summary] to write: return (return[0]) in RequestURI |
@@ -261,20 +249,12 @@
261249
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
262250
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
263251
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
264-
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
265-
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
266-
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
267-
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
268-
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
269-
| file://:0:0:0:0 | parameter -1 of Sub | file://:0:0:0:0 | [summary] to write: return (return[0]) in Sub |
270252
| file://:0:0:0:0 | parameter -1 of Sub | file://:0:0:0:0 | [summary] to write: return (return[0]) in Sub |
271253
| file://:0:0:0:0 | parameter -1 of Swap | file://:0:0:0:0 | [summary] to write: return (return[0]) in Swap |
272254
| file://:0:0:0:0 | parameter -1 of Swap | file://:0:0:0:0 | [summary] to write: return (return[0]) in Swap |
273255
| file://:0:0:0:0 | parameter -1 of Swap | file://:0:0:0:0 | [summary] to write: return (return[0]) in Swap |
274256
| file://:0:0:0:0 | parameter -1 of Swap | file://:0:0:0:0 | [summary] to write: return (return[0]) in Swap |
275257
| file://:0:0:0:0 | parameter -1 of SyscallConn | file://:0:0:0:0 | [summary] to write: return (return[0]) in SyscallConn |
276-
| file://:0:0:0:0 | parameter -1 of SyscallConn | file://:0:0:0:0 | [summary] to write: return (return[0]) in SyscallConn |
277-
| file://:0:0:0:0 | parameter -1 of Token | file://:0:0:0:0 | [summary] to write: return (return[0]) in Token |
278258
| file://:0:0:0:0 | parameter -1 of Token | file://:0:0:0:0 | [summary] to write: return (return[0]) in Token |
279259
| file://:0:0:0:0 | parameter -1 of TryRecv | file://:0:0:0:0 | [summary] to write: return (return[0]) in TryRecv |
280260
| file://:0:0:0:0 | parameter -1 of UnsafeAddr | file://:0:0:0:0 | [summary] to write: return (return[0]) in UnsafeAddr |
@@ -283,7 +263,27 @@
283263
| file://:0:0:0:0 | parameter -1 of WriteTo | file://:0:0:0:0 | [summary] to write: argument 0 in WriteTo |
284264
| file://:0:0:0:0 | parameter -1 of WriteTo | file://:0:0:0:0 | [summary] to write: argument 0 in WriteTo |
285265
| file://:0:0:0:0 | parameter -1 of WriteTo | file://:0:0:0:0 | [summary] to write: argument 0 in WriteTo |
286-
| file://:0:0:0:0 | parameter -1 of WriteTo | file://:0:0:0:0 | [summary] to write: argument 0 in WriteTo |
266+
| file://:0:0:0:0 | parameter -2 of Glob | file://:0:0:0:0 | [summary] to write: return (return[0]) in Glob |
267+
| file://:0:0:0:0 | parameter -2 of GoString | file://:0:0:0:0 | [summary] to write: return (return[0]) in GoString |
268+
| file://:0:0:0:0 | parameter -2 of Info | file://:0:0:0:0 | [summary] to write: return (return[0]) in Info |
269+
| file://:0:0:0:0 | parameter -2 of Name | file://:0:0:0:0 | [summary] to write: return (return[0]) in Name |
270+
| file://:0:0:0:0 | parameter -2 of Open | file://:0:0:0:0 | [summary] to write: return (return[0]) in Open |
271+
| file://:0:0:0:0 | parameter -2 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
272+
| file://:0:0:0:0 | parameter -2 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
273+
| file://:0:0:0:0 | parameter -2 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
274+
| file://:0:0:0:0 | parameter -2 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
275+
| file://:0:0:0:0 | parameter -2 of ReadAt | file://:0:0:0:0 | [summary] to write: argument 0 in ReadAt |
276+
| file://:0:0:0:0 | parameter -2 of ReadDir | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadDir |
277+
| file://:0:0:0:0 | parameter -2 of ReadFile | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadFile |
278+
| file://:0:0:0:0 | parameter -2 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
279+
| file://:0:0:0:0 | parameter -2 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
280+
| file://:0:0:0:0 | parameter -2 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
281+
| file://:0:0:0:0 | parameter -2 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
282+
| file://:0:0:0:0 | parameter -2 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
283+
| file://:0:0:0:0 | parameter -2 of Sub | file://:0:0:0:0 | [summary] to write: return (return[0]) in Sub |
284+
| file://:0:0:0:0 | parameter -2 of SyscallConn | file://:0:0:0:0 | [summary] to write: return (return[0]) in SyscallConn |
285+
| file://:0:0:0:0 | parameter -2 of Token | file://:0:0:0:0 | [summary] to write: return (return[0]) in Token |
286+
| file://:0:0:0:0 | parameter -2 of WriteTo | file://:0:0:0:0 | [summary] to write: argument 0 in WriteTo |
287287
| main.go:26:11:26:17 | type assertion | main.go:26:2:26:17 | ... := ...[0] |
288288
| main.go:26:11:26:17 | type assertion | main.go:26:2:26:17 | ... := ...[1] |
289289
| main.go:38:13:38:13 | 1 | main.go:38:7:38:20 | slice literal |

0 commit comments

Comments
 (0)