LEFT | RIGHT |
(no file at all) | |
| 1 // errchk -0 $G -sm $D/$F.go |
| 2 |
| 3 // Copyright 2010 The Go Authors. All rights reserved. |
| 4 // Use of this source code is governed by a BSD-style |
| 5 // license that can be found in the LICENSE file. |
| 6 |
| 7 package foo |
| 8 |
| 9 import "unsafe" |
| 10 |
| 11 var gxx *int |
| 12 |
| 13 func foo1(x int) { // ERROR "moved to heap: NAME-x" |
| 14 gxx = &x |
| 15 } |
| 16 |
| 17 func foo2(yy *int) { // ERROR "leaking param: NAME-yy" |
| 18 gxx = yy |
| 19 } |
| 20 |
| 21 func foo3(x int) *int { // ERROR "moved to heap: NAME-x" |
| 22 return &x |
| 23 } |
| 24 |
| 25 type T *T |
| 26 func foo3b(t T) { // ERROR "leaking param: NAME-t" |
| 27 *t = t |
| 28 } |
| 29 |
| 30 // xx isn't going anywhere, so use of yy is ok |
| 31 func foo4(xx, yy *int) { |
| 32 xx = yy |
| 33 } |
| 34 |
| 35 // xx isn't going anywhere, so taking address of yy is ok |
| 36 func foo5(xx **int, yy *int) { |
| 37 xx = &yy |
| 38 } |
| 39 |
| 40 func foo6(xx **int, yy *int) { // ERROR "leaking param: NAME-yy" |
| 41 *xx = yy |
| 42 } |
| 43 |
| 44 func foo7(xx **int, yy *int) { |
| 45 **xx = *yy |
| 46 } |
| 47 |
| 48 func foo8(xx, yy *int) int { |
| 49 xx = yy |
| 50 return *xx |
| 51 } |
| 52 |
| 53 func foo9(xx, yy *int) *int { // ERROR "leaking param: NAME-xx" "leaking param:
NAME-yy" |
| 54 xx = yy |
| 55 return xx |
| 56 } |
| 57 |
| 58 func foo10(xx, yy *int) { |
| 59 *xx = *yy |
| 60 } |
| 61 |
| 62 func foo11() int { |
| 63 x, y := 0, 42 |
| 64 xx := &x |
| 65 yy := &y |
| 66 *xx = *yy |
| 67 return x |
| 68 } |
| 69 |
| 70 |
| 71 var xxx **int |
| 72 |
| 73 func foo12(yyy **int) { // ERROR "leaking param: NAME-yyy" |
| 74 xxx = yyy |
| 75 } |
| 76 |
| 77 func foo13(yyy **int) { |
| 78 *xxx = *yyy |
| 79 } |
| 80 |
| 81 func foo14(yyy **int) { |
| 82 **xxx = **yyy |
| 83 } |
| 84 |
| 85 func foo15(yy *int) { // ERROR "moved to heap: NAME-yy" |
| 86 xxx = &yy |
| 87 } |
| 88 |
| 89 func foo16(yy *int) { // ERROR "leaking param: NAME-yy" |
| 90 *xxx = yy |
| 91 } |
| 92 |
| 93 func foo17(yy *int) { |
| 94 **xxx = *yy |
| 95 } |
| 96 |
| 97 func foo18(y int) { // ERROR "moved to heap: "NAME-y" |
| 98 *xxx = &y |
| 99 } |
| 100 |
| 101 func foo19(y int) { |
| 102 **xxx = y |
| 103 } |
| 104 |
| 105 type Bar struct { |
| 106 i int |
| 107 ii *int |
| 108 } |
| 109 |
| 110 func NewBar() *Bar { |
| 111 return &Bar{ 42, nil } |
| 112 } |
| 113 |
| 114 func NewBarp(x *int) *Bar { // ERROR "leaking param: NAME-x" |
| 115 return &Bar{ 42, x } |
| 116 } |
| 117 |
| 118 func NewBarp2(x *int) *Bar { |
| 119 return &Bar{ *x, nil } |
| 120 } |
| 121 |
| 122 func (b *Bar) NoLeak() int { |
| 123 return *(b.ii) |
| 124 } |
| 125 |
| 126 func (b *Bar) AlsoNoLeak() *int { |
| 127 return b.ii |
| 128 } |
| 129 |
| 130 type Bar2 struct { |
| 131 i [12]int |
| 132 ii []int |
| 133 } |
| 134 |
| 135 func NewBar2() *Bar2 { |
| 136 return &Bar2{ [12]int{ 42 }, nil } |
| 137 } |
| 138 |
| 139 func (b *Bar2) NoLeak() int { |
| 140 return b.i[0] |
| 141 } |
| 142 |
| 143 func (b *Bar2) Leak() []int { // ERROR "leaking param: NAME-b" |
| 144 return b.i[:] |
| 145 } |
| 146 |
| 147 func (b *Bar2) AlsoNoLeak() []int { |
| 148 return b.ii[0:1] |
| 149 } |
| 150 |
| 151 func (b *Bar2) LeakSelf() { // ERROR "leaking param: NAME-b" |
| 152 b.ii = b.i[0:4] |
| 153 } |
| 154 |
| 155 func (b *Bar2) LeakSelf2() { // ERROR "leaking param: NAME-b" |
| 156 var buf []int |
| 157 buf = b.i[0:] |
| 158 b.ii = buf |
| 159 } |
| 160 |
| 161 func foo21() func() int { |
| 162 x := 42 // ERROR "moved to heap: NAME-x" |
| 163 return func() int { |
| 164 return x |
| 165 } |
| 166 } |
| 167 |
| 168 func foo22() int { |
| 169 x := 42 |
| 170 return func() int { |
| 171 return x |
| 172 }() |
| 173 } |
| 174 |
| 175 func foo23(x int) func() int { // ERROR "moved to heap: NAME-x" |
| 176 return func() int { |
| 177 return x |
| 178 } |
| 179 } |
| 180 |
| 181 func foo23a(x int) (func() int) { // ERROR "moved to heap: NAME-x" |
| 182 f := func() int { |
| 183 return x |
| 184 } |
| 185 return f |
| 186 } |
| 187 |
| 188 func foo23b(x int) *(func() int) { // ERROR "moved to heap: NAME-x" |
| 189 f := func() int { return x } // ERROR "moved to heap: NAME-f" |
| 190 return &f |
| 191 } |
| 192 |
| 193 func foo24(x int) int { |
| 194 return func() int { |
| 195 return x |
| 196 }() |
| 197 } |
| 198 |
| 199 |
| 200 var x *int |
| 201 |
| 202 func fooleak(xx *int) int { // ERROR "leaking param: NAME-xx" |
| 203 x = xx |
| 204 return *x |
| 205 } |
| 206 |
| 207 func foonoleak(xx *int) int { |
| 208 return *x + *xx |
| 209 } |
| 210 |
| 211 func foo31(x int) int { // ERROR "moved to heap: NAME-x" |
| 212 return fooleak(&x) |
| 213 } |
| 214 |
| 215 func foo32(x int) int { |
| 216 return foonoleak(&x) |
| 217 } |
| 218 |
| 219 type Foo struct { |
| 220 xx *int |
| 221 x int |
| 222 } |
| 223 |
| 224 var F Foo |
| 225 var pf *Foo |
| 226 |
| 227 func (f *Foo) fooleak() { // ERROR "leaking param: NAME-f" |
| 228 pf = f |
| 229 } |
| 230 |
| 231 func (f *Foo) foonoleak() { |
| 232 F.x = f.x |
| 233 } |
| 234 |
| 235 func (f *Foo) Leak() { // ERROR "leaking param: NAME-f" |
| 236 f.fooleak() |
| 237 } |
| 238 |
| 239 func (f *Foo) NoLeak() { |
| 240 f.foonoleak() |
| 241 } |
| 242 |
| 243 |
| 244 func foo41(x int) { // ERROR "moved to heap: NAME-x" |
| 245 F.xx = &x |
| 246 } |
| 247 |
| 248 func (f *Foo) foo42(x int) { // ERROR "moved to heap: NAME-x" |
| 249 f.xx = &x |
| 250 } |
| 251 |
| 252 func foo43(f *Foo, x int) { // ERROR "moved to heap: NAME-x" |
| 253 f.xx = &x |
| 254 } |
| 255 |
| 256 func foo44(yy *int) { // ERROR "leaking param: NAME-yy" |
| 257 F.xx = yy |
| 258 } |
| 259 |
| 260 func (f *Foo) foo45() { |
| 261 F.x = f.x· |
| 262 } |
| 263 |
| 264 func (f *Foo) foo46() { |
| 265 F.xx = f.xx· |
| 266 } |
| 267 |
| 268 func (f *Foo) foo47() { // ERROR "leaking param: NAME-f" |
| 269 f.xx = &f.x |
| 270 } |
| 271 |
| 272 |
| 273 var ptrSlice []*int |
| 274 |
| 275 func foo50(i *int) { // ERROR "leaking param: NAME-i" |
| 276 ptrSlice[0] = i |
| 277 } |
| 278 |
| 279 |
| 280 var ptrMap map[*int]*int |
| 281 |
| 282 func foo51(i *int) { // ERROR "leaking param: NAME-i" |
| 283 ptrMap[i] = i |
| 284 } |
| 285 |
| 286 |
| 287 func indaddr1(x int) *int { // ERROR "moved to heap: NAME-x" |
| 288 return &x |
| 289 } |
| 290 |
| 291 func indaddr2(x *int) *int { // ERROR "leaking param: NAME-x" |
| 292 return *&x |
| 293 } |
| 294 |
| 295 func indaddr3(x *int32) *int { // ERROR "leaking param: NAME-x" |
| 296 return *(**int)(unsafe.Pointer(&x)) |
| 297 } |
| 298 |
| 299 // From package math: |
| 300 |
| 301 func Float32bits(f float32) uint32 { |
| 302 return *(*uint32)(unsafe.Pointer(&f)) |
| 303 } |
| 304 |
| 305 func Float32frombits(b uint32) float32 { |
| 306 return *(*float32)(unsafe.Pointer(&b)) |
| 307 } |
| 308 |
| 309 func Float64bits(f float64) uint64 { |
| 310 return *(*uint64)(unsafe.Pointer(&f)) |
| 311 } |
| 312 |
| 313 func Float64frombits(b uint64) float64 { |
| 314 return *(*float64)(unsafe.Pointer(&b)) |
| 315 } |
| 316 |
| 317 // contrast with |
| 318 func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: NAME-f" |
| 319 return (*uint64)(unsafe.Pointer(&f)) |
| 320 } |
| 321 |
| 322 func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: NAME-f" |
| 323 return (*uint64)(unsafe.Pointer(f)) |
| 324 } |
| 325 |
| 326 func typesw(i interface{}) *int { // ERROR "leaking param: NAME-i" |
| 327 switch val := i.(type) { |
| 328 case *int: |
| 329 return val |
| 330 case *int8: |
| 331 v := int(*val) // ERROR "moved to heap: NAME-v" |
| 332 return &v |
| 333 } |
| 334 return nil |
| 335 } |
| 336 |
| 337 func exprsw(i *int) *int { // ERROR "leaking param: NAME-i" |
| 338 switch j := i; *j + 110 { |
| 339 case 12: |
| 340 return j |
| 341 case 42: |
| 342 return nil |
| 343 } |
| 344 return nil |
| 345 |
| 346 } |
| 347 |
| 348 // assigning to an array element is like assigning to the array |
| 349 func foo60(i *int) *int { // ERROR "leaking param: NAME-i" |
| 350 var a [12]*int |
| 351 a[0] = i |
| 352 return a[1] |
| 353 } |
| 354 |
| 355 func foo60a(i *int) *int { |
| 356 var a [12]*int |
| 357 a[0] = i |
| 358 return nil |
| 359 } |
| 360 |
| 361 // assigning to a struct field is like assigning to the struct |
| 362 func foo61(i *int) *int { // ERROR "leaking param: NAME-i" |
| 363 type S struct { |
| 364 a,b *int |
| 365 } |
| 366 var s S |
| 367 s.a = i |
| 368 return s.b |
| 369 } |
| 370 |
| 371 func foo61a(i *int) *int { |
| 372 type S struct { |
| 373 a,b *int |
| 374 } |
| 375 var s S |
| 376 s.a = i |
| 377 return nil |
| 378 } |
| 379 |
| 380 // assigning to a struct field is like assigning to the struct but |
| 381 // here this subtlety is lost, since s.a counts as an assignment to a |
| 382 // track-losing dereference. |
| 383 func foo62(i *int) *int { // ERROR "leaking param: NAME-i" |
| 384 type S struct { |
| 385 a,b *int |
| 386 } |
| 387 s := new(S) |
| 388 s.a = i |
| 389 return nil // s.b |
| 390 } |
| 391 |
| 392 |
| 393 type M interface { M() } |
| 394 |
| 395 func foo63(m M) { |
| 396 } |
| 397 |
| 398 func foo64(m M) { // ERROR "leaking param: NAME-m" |
| 399 m.M() |
| 400 } |
| 401 |
| 402 type MV int |
| 403 func (MV) M() {} |
| 404 |
| 405 func foo65() { |
| 406 var mv MV |
| 407 foo63(&mv) |
| 408 } |
| 409 |
| 410 func foo66() { |
| 411 var mv MV // ERROR "moved to heap: NAME-mv" |
| 412 foo64(&mv) |
| 413 } |
| 414 |
| 415 func foo67() { |
| 416 var mv MV |
| 417 foo63(mv) |
| 418 } |
| 419 |
| 420 func foo68() { |
| 421 var mv MV |
| 422 foo64(mv) // escapes but it's an int so irrelevant |
| 423 } |
| 424 |
| 425 func foo69(m M) { // ERROR "leaking param: NAME-m" |
| 426 foo64(m) |
| 427 } |
| 428 |
| 429 func foo70(mv1 *MV, m M) { // ERROR "leaking param: NAME-mv1" "leaking param: N
AME-m" |
| 430 m = mv1 |
| 431 foo64(m) |
| 432 } |
| 433 |
| 434 func foo71(x *int) []*int { // ERROR "leaking param: NAME-x" |
| 435 var y []*int |
| 436 y = append(y, x) |
| 437 return y |
| 438 } |
| 439 |
| 440 func foo71a(x int) []*int { // ERROR "moved to heap: NAME-x" |
| 441 var y []*int |
| 442 y = append(y, &x) |
| 443 return y |
| 444 } |
| 445 |
| 446 func foo72() { |
| 447 var x int |
| 448 var y [1]*int |
| 449 y[0] = &x |
| 450 } |
| 451 |
| 452 func foo72aa() [10]*int { |
| 453 var x int // ERROR "moved to heap: NAME-x" |
| 454 var y [10]*int |
| 455 y[0] = &x |
| 456 return y |
| 457 } |
| 458 |
| 459 func foo72a() { |
| 460 var y [10]*int |
| 461 for i := 0; i < 10; i++ { |
| 462 x := i // not moved to heap b/c y goes nowhere |
| 463 y[i] = &x |
| 464 } |
| 465 return |
| 466 } |
| 467 |
| 468 func foo72b() [10]*int { |
| 469 var y [10]*int |
| 470 for i := 0; i < 10; i++ { |
| 471 x := i // ERROR "moved to heap: NAME-x" |
| 472 y[i] = &x |
| 473 } |
| 474 return y |
| 475 } |
| 476 |
| 477 |
| 478 // issue 2145 |
| 479 func foo73() { |
| 480 s := []int{3,2,1} |
| 481 for _, v := range s { |
| 482 vv := v // ERROR "moved to heap: NAME-vv" |
| 483 defer func() { // "func literal escapes its scope" "&vv escape
s its scope" |
| 484 println(vv) |
| 485 }() |
| 486 } |
| 487 } |
| 488 |
| 489 func foo74() { |
| 490 s := []int{3,2,1} |
| 491 for _, v := range s { |
| 492 vv := v // ERROR "moved to heap: NAME-vv" |
| 493 fn := func() { // "func literal escapes its scope" "&vv escape
s its scope" |
| 494 println(vv) |
| 495 } |
| 496 defer fn() |
| 497 } |
| 498 } |
| 499 |
| 500 func myprint(y *int, x ...interface{}) *int { // ERROR "leaking param: NAME-y" |
| 501 return y |
| 502 } |
| 503 |
| 504 func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "leaking param:
NAME-x" |
| 505 return &x[0] |
| 506 } |
| 507 |
| 508 func foo75(z *int) { // ERROR "leaking param: NAME-z" |
| 509 myprint(z, 1, 2, 3) |
| 510 } |
| 511 |
| 512 func foo75a(z *int) { |
| 513 myprint1(z, 1, 2, 3) // "[.][.][.] argument escapes to heap" |
| 514 } |
| 515 |
| 516 func foo76(z *int) { |
| 517 myprint(nil, z) |
| 518 } |
| 519 |
| 520 func foo76a(z *int) { // ERROR "leaking param: NAME-z" |
| 521 myprint1(nil, z) // "[.][.][.] argument escapes to heap" |
| 522 } |
| 523 |
| 524 func foo76b() { |
| 525 myprint(nil, 1, 2, 3) |
| 526 } |
| 527 |
| 528 func foo76c() { |
| 529 myprint1(nil, 1, 2, 3) // "[.][.][.] argument escapes to heap" |
| 530 } |
| 531 |
| 532 func foo76d() { |
| 533 defer myprint(nil, 1, 2, 3) |
| 534 } |
| 535 |
| 536 func foo76e() { |
| 537 defer myprint1(nil, 1, 2, 3) // "[.][.][.] argument escapes to heap" |
| 538 } |
| 539 |
| 540 func foo76f() { |
| 541 for { |
| 542 defer myprint(nil, 1, 2, 3) // "[.][.][.] argument escapes its s
cope" |
| 543 } |
| 544 } |
| 545 |
| 546 func foo76g() { |
| 547 for { |
| 548 defer myprint1(nil, 1, 2, 3) // "[.][.][.] argument escapes to h
eap" |
| 549 } |
| 550 } |
| 551 |
| 552 func foo77(z []interface{}) { |
| 553 myprint(nil, z...) // z does not escape |
| 554 } |
| 555 |
| 556 func foo77a(z []interface{}) { // ERROR "leaking param: NAME-z" |
| 557 myprint1(nil, z...) |
| 558 } |
| 559 |
| 560 func foo78(z int) *int { // ERROR "moved to heap: NAME-z" |
| 561 return &z // "&z escapes" |
| 562 } |
| 563 |
| 564 func foo78a(z int) *int { // ERROR "moved to heap: NAME-z" |
| 565 y := &z |
| 566 x := &y |
| 567 return *x // really return y |
| 568 } |
| 569 |
| 570 func foo79() *int { |
| 571 return new(int) // "moved to heap: new[(]int[)]" |
| 572 } |
| 573 |
| 574 func foo80() *int { |
| 575 var z *int |
| 576 for { |
| 577 z = new(int) // "new[(]int[)] escapes its scope" |
| 578 } |
| 579 _ = z |
| 580 return nil |
| 581 } |
| 582 |
| 583 func foo81() *int { |
| 584 for { |
| 585 z := new(int) |
| 586 _ = z |
| 587 } |
| 588 return nil |
| 589 } |
| 590 |
| 591 type Fooer interface { |
| 592 Foo() |
| 593 } |
| 594 |
| 595 type LimitedFooer struct { |
| 596 Fooer |
| 597 N int64 |
| 598 } |
| 599 |
| 600 func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: NAME-r" |
| 601 return &LimitedFooer{r, n} |
| 602 } |
| 603 |
| 604 func foo90(x *int) map[*int]*int { // ERROR "leaking param: NAME-x" |
| 605 return map[*int]*int{ nil: x } |
| 606 } |
| 607 |
| 608 func foo91(x *int) map[*int]*int { // ERROR "leaking param: NAME-x" |
| 609 return map[*int]*int{ x:nil } |
| 610 } |
| 611 |
| 612 func foo92(x *int) [2]*int { // ERROR "leaking param: NAME-x" |
| 613 return [2]*int{ x, nil } |
| 614 } |
| 615 |
LEFT | RIGHT |