1
2
3
4
5 package pointer
6
7
8
9
10
11
12
13
14
15
16
17
18 import (
19 "fmt"
20 "go/types"
21
22 "golang.org/x/tools/go/ssa"
23 )
24
25
26
27
28
29 type intrinsic func(a *analysis, cgn *cgnode)
30
31
32
33 var intrinsicsByName = make(map[string]intrinsic)
34
35 func init() {
36
37
38
39 for name, fn := range map[string]intrinsic{
40
41 "bytes.Equal": ext۰NoEffect,
42 "bytes.IndexByte": ext۰NoEffect,
43 "crypto/aes.decryptBlockAsm": ext۰NoEffect,
44 "crypto/aes.encryptBlockAsm": ext۰NoEffect,
45 "crypto/aes.expandKeyAsm": ext۰NoEffect,
46 "crypto/aes.hasAsm": ext۰NoEffect,
47 "crypto/md5.block": ext۰NoEffect,
48 "crypto/rc4.xorKeyStream": ext۰NoEffect,
49 "crypto/sha1.block": ext۰NoEffect,
50 "crypto/sha256.block": ext۰NoEffect,
51 "hash/crc32.castagnoliSSE42": ext۰NoEffect,
52 "hash/crc32.haveSSE42": ext۰NoEffect,
53 "math.Abs": ext۰NoEffect,
54 "math.Acos": ext۰NoEffect,
55 "math.Asin": ext۰NoEffect,
56 "math.Atan": ext۰NoEffect,
57 "math.Atan2": ext۰NoEffect,
58 "math.Ceil": ext۰NoEffect,
59 "math.Cos": ext۰NoEffect,
60 "math.Dim": ext۰NoEffect,
61 "math.Exp": ext۰NoEffect,
62 "math.Exp2": ext۰NoEffect,
63 "math.Expm1": ext۰NoEffect,
64 "math.Float32bits": ext۰NoEffect,
65 "math.Float32frombits": ext۰NoEffect,
66 "math.Float64bits": ext۰NoEffect,
67 "math.Float64frombits": ext۰NoEffect,
68 "math.Floor": ext۰NoEffect,
69 "math.Frexp": ext۰NoEffect,
70 "math.Hypot": ext۰NoEffect,
71 "math.Ldexp": ext۰NoEffect,
72 "math.Log": ext۰NoEffect,
73 "math.Log10": ext۰NoEffect,
74 "math.Log1p": ext۰NoEffect,
75 "math.Log2": ext۰NoEffect,
76 "math.Max": ext۰NoEffect,
77 "math.Min": ext۰NoEffect,
78 "math.Mod": ext۰NoEffect,
79 "math.Modf": ext۰NoEffect,
80 "math.Remainder": ext۰NoEffect,
81 "math.Sin": ext۰NoEffect,
82 "math.Sincos": ext۰NoEffect,
83 "math.Sqrt": ext۰NoEffect,
84 "math.Tan": ext۰NoEffect,
85 "math.Trunc": ext۰NoEffect,
86 "math/big.addMulVVW": ext۰NoEffect,
87 "math/big.addVV": ext۰NoEffect,
88 "math/big.addVW": ext۰NoEffect,
89 "math/big.bitLen": ext۰NoEffect,
90 "math/big.divWVW": ext۰NoEffect,
91 "math/big.divWW": ext۰NoEffect,
92 "math/big.mulAddVWW": ext۰NoEffect,
93 "math/big.mulWW": ext۰NoEffect,
94 "math/big.shlVU": ext۰NoEffect,
95 "math/big.shrVU": ext۰NoEffect,
96 "math/big.subVV": ext۰NoEffect,
97 "math/big.subVW": ext۰NoEffect,
98 "net.runtime_Semacquire": ext۰NoEffect,
99 "net.runtime_Semrelease": ext۰NoEffect,
100 "net.runtime_pollClose": ext۰NoEffect,
101 "net.runtime_pollOpen": ext۰NoEffect,
102 "net.runtime_pollReset": ext۰NoEffect,
103 "net.runtime_pollServerInit": ext۰NoEffect,
104 "net.runtime_pollSetDeadline": ext۰NoEffect,
105 "net.runtime_pollUnblock": ext۰NoEffect,
106 "net.runtime_pollWait": ext۰NoEffect,
107 "net.runtime_pollWaitCanceled": ext۰NoEffect,
108 "os.epipecheck": ext۰NoEffect,
109
110 "runtime.SetFinalizer": ext۰runtime۰SetFinalizer,
111 "strings.IndexByte": ext۰NoEffect,
112 "sync.runtime_Semacquire": ext۰NoEffect,
113 "sync.runtime_Semrelease": ext۰NoEffect,
114 "sync.runtime_Syncsemacquire": ext۰NoEffect,
115 "sync.runtime_Syncsemcheck": ext۰NoEffect,
116 "sync.runtime_Syncsemrelease": ext۰NoEffect,
117 "sync.runtime_procPin": ext۰NoEffect,
118 "sync.runtime_procUnpin": ext۰NoEffect,
119 "sync.runtime_registerPool": ext۰NoEffect,
120 "sync/atomic.AddInt32": ext۰NoEffect,
121 "sync/atomic.AddInt64": ext۰NoEffect,
122 "sync/atomic.AddUint32": ext۰NoEffect,
123 "sync/atomic.AddUint64": ext۰NoEffect,
124 "sync/atomic.AddUintptr": ext۰NoEffect,
125 "sync/atomic.CompareAndSwapInt32": ext۰NoEffect,
126 "sync/atomic.CompareAndSwapUint32": ext۰NoEffect,
127 "sync/atomic.CompareAndSwapUint64": ext۰NoEffect,
128 "sync/atomic.CompareAndSwapUintptr": ext۰NoEffect,
129 "sync/atomic.LoadInt32": ext۰NoEffect,
130 "sync/atomic.LoadInt64": ext۰NoEffect,
131 "sync/atomic.LoadPointer": ext۰NoEffect,
132 "sync/atomic.LoadUint32": ext۰NoEffect,
133 "sync/atomic.LoadUint64": ext۰NoEffect,
134 "sync/atomic.LoadUintptr": ext۰NoEffect,
135 "sync/atomic.StoreInt32": ext۰NoEffect,
136 "sync/atomic.StorePointer": ext۰NoEffect,
137 "sync/atomic.StoreUint32": ext۰NoEffect,
138 "sync/atomic.StoreUintptr": ext۰NoEffect,
139 "syscall.Close": ext۰NoEffect,
140 "syscall.Exit": ext۰NoEffect,
141 "syscall.Getpid": ext۰NoEffect,
142 "syscall.Getwd": ext۰NoEffect,
143 "syscall.Kill": ext۰NoEffect,
144 "syscall.RawSyscall": ext۰NoEffect,
145 "syscall.RawSyscall6": ext۰NoEffect,
146 "syscall.Syscall": ext۰NoEffect,
147 "syscall.Syscall6": ext۰NoEffect,
148 "syscall.runtime_AfterFork": ext۰NoEffect,
149 "syscall.runtime_BeforeFork": ext۰NoEffect,
150 "syscall.setenv_c": ext۰NoEffect,
151 "time.Sleep": ext۰NoEffect,
152 "time.now": ext۰NoEffect,
153 "time.startTimer": ext۰time۰startTimer,
154 "time.stopTimer": ext۰NoEffect,
155 } {
156 intrinsicsByName[name] = fn
157 }
158 }
159
160
161
162 func (a *analysis) findIntrinsic(fn *ssa.Function) intrinsic {
163
164
165 impl, ok := a.intrinsics[fn]
166 if !ok {
167 impl = intrinsicsByName[fn.String()]
168
169 if a.isReflect(fn) {
170 if !a.config.Reflection {
171 impl = ext۰NoEffect
172 } else if impl == nil {
173
174 impl = ext۰NotYetImplemented
175 }
176 } else if impl == nil && fn.Pkg != nil && fn.Pkg.Pkg.Path() == "runtime" {
177
178
179
180 impl = ext۰NoEffect
181 }
182
183 a.intrinsics[fn] = impl
184 }
185 return impl
186 }
187
188
189 func (a *analysis) isReflect(fn *ssa.Function) bool {
190 if a.reflectValueObj == nil {
191 return false
192 }
193 reflectPackage := a.reflectValueObj.Pkg()
194 if fn.Pkg != nil && fn.Pkg.Pkg == reflectPackage {
195 return true
196 }
197
198
199
200 if recv := fn.Signature.Recv(); recv != nil {
201 if named, ok := deref(recv.Type()).(*types.Named); ok {
202 if named.Obj().Pkg() == reflectPackage {
203 return true
204 }
205 }
206 }
207 return false
208 }
209
210
211
212
213
214
215
216
217
218
219
220
221
222 func ext۰NoEffect(a *analysis, cgn *cgnode) {}
223
224 func ext۰NotYetImplemented(a *analysis, cgn *cgnode) {
225 fn := cgn.fn
226 a.warnf(fn.Pos(), "unsound: intrinsic treatment of %s not yet implemented", fn)
227 }
228
229
230
231
232 type runtimeSetFinalizerConstraint struct {
233 targets nodeid
234 f nodeid
235 x nodeid
236 }
237
238 func (c *runtimeSetFinalizerConstraint) ptr() nodeid { return c.f }
239 func (c *runtimeSetFinalizerConstraint) presolve(h *hvn) {
240 h.markIndirect(onodeid(c.targets), "SetFinalizer.targets")
241 }
242 func (c *runtimeSetFinalizerConstraint) renumber(mapping []nodeid) {
243 c.targets = mapping[c.targets]
244 c.f = mapping[c.f]
245 c.x = mapping[c.x]
246 }
247
248 func (c *runtimeSetFinalizerConstraint) String() string {
249 return fmt.Sprintf("runtime.SetFinalizer(n%d, n%d)", c.x, c.f)
250 }
251
252 func (c *runtimeSetFinalizerConstraint) solve(a *analysis, delta *nodeset) {
253 for _, fObj := range delta.AppendTo(a.deltaSpace) {
254 tDyn, f, indirect := a.taggedValue(nodeid(fObj))
255 if indirect {
256
257
258 panic("indirect tagged object")
259 }
260
261 tSig, ok := tDyn.Underlying().(*types.Signature)
262 if !ok {
263 continue
264 }
265 if tSig.Recv() != nil {
266 panic(tSig)
267 }
268 if tSig.Params().Len() != 1 {
269 continue
270 }
271
272
273 tx := tSig.Params().At(0).Type()
274 tmp := a.addNodes(tx, "SetFinalizer.tmp")
275 a.typeAssert(tx, tmp, c.x, false)
276
277
278 a.store(f, tmp, 1, a.sizeof(tx))
279
280
281 if a.onlineCopy(c.targets, f) {
282 a.addWork(c.targets)
283 }
284 }
285 }
286
287 func ext۰runtime۰SetFinalizer(a *analysis, cgn *cgnode) {
288
289 targets := a.addOneNode(tInvalid, "SetFinalizer.targets", nil)
290 cgn.sites = append(cgn.sites, &callsite{targets: targets})
291 params := a.funcParams(cgn.obj)
292 a.addConstraint(&runtimeSetFinalizerConstraint{
293 targets: targets,
294 x: params,
295 f: params + 1,
296 })
297 }
298
299
300
301
302 type timeStartTimerConstraint struct {
303 targets nodeid
304 t nodeid
305 }
306
307 func (c *timeStartTimerConstraint) ptr() nodeid { return c.t }
308 func (c *timeStartTimerConstraint) presolve(h *hvn) {
309 h.markIndirect(onodeid(c.targets), "StartTimer.targets")
310 }
311 func (c *timeStartTimerConstraint) renumber(mapping []nodeid) {
312 c.targets = mapping[c.targets]
313 c.t = mapping[c.t]
314 }
315
316 func (c *timeStartTimerConstraint) String() string {
317 return fmt.Sprintf("time.startTimer(n%d)", c.t)
318 }
319
320 func (c *timeStartTimerConstraint) solve(a *analysis, delta *nodeset) {
321 for _, tObj := range delta.AppendTo(a.deltaSpace) {
322 t := nodeid(tObj)
323
324
325
326
327
328
329
330
331
332
333
334
335
336 f := t + 4
337 arg := t + 5
338
339
340
341 a.store(f, arg, 1, 1)
342
343
344 if a.onlineCopy(c.targets, f) {
345 a.addWork(c.targets)
346 }
347 }
348 }
349
350 func ext۰time۰startTimer(a *analysis, cgn *cgnode) {
351
352 targets := a.addOneNode(tInvalid, "startTimer.targets", nil)
353 cgn.sites = append(cgn.sites, &callsite{targets: targets})
354 params := a.funcParams(cgn.obj)
355 a.addConstraint(&timeStartTimerConstraint{
356 targets: targets,
357 t: params,
358 })
359 }
360
View as plain text