github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/test/escape_param.go (about)

     1  // errorcheck -0 -m -l
     2  
     3  // Copyright 2015 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  // Test escape analysis for function parameters.
     8  
     9  // In this test almost everything is BAD except the simplest cases
    10  // where input directly flows to output.
    11  
    12  package escape
    13  
    14  var sink interface{}
    15  
    16  // in -> out
    17  func param0(p *int) *int { // ERROR "leaking param: p to result ~r1"
    18  	return p
    19  }
    20  
    21  func caller0a() {
    22  	i := 0
    23  	_ = param0(&i) // ERROR "caller0a &i does not escape$"
    24  }
    25  
    26  func caller0b() {
    27  	i := 0            // ERROR "moved to heap: i$"
    28  	sink = param0(&i) // ERROR "&i escapes to heap$" "param0\(&i\) escapes to heap"
    29  }
    30  
    31  // in, in -> out, out
    32  func param1(p1, p2 *int) (*int, *int) { // ERROR "leaking param: p1 to result ~r2" "leaking param: p2 to result ~r3"
    33  	return p1, p2
    34  }
    35  
    36  func caller1() {
    37  	i := 0 // ERROR "moved to heap: i$"
    38  	j := 0
    39  	sink, _ = param1(&i, &j) // ERROR "&i escapes to heap$" "caller1 &j does not escape$"
    40  }
    41  
    42  // in -> other in
    43  func param2(p1 *int, p2 **int) { // ERROR "leaking param: p1$" "param2 p2 does not escape$"
    44  	*p2 = p1
    45  }
    46  
    47  func caller2a() {
    48  	i := 0 // ERROR "moved to heap: i$"
    49  	var p *int
    50  	param2(&i, &p) // ERROR "&i escapes to heap$" "caller2a &p does not escape$"
    51  	_ = p
    52  }
    53  
    54  func caller2b() {
    55  	i := 0 // ERROR "moved to heap: i$"
    56  	var p *int
    57  	param2(&i, &p) // ERROR "&i escapes to heap$" "caller2b &p does not escape$"
    58  	sink = p       // ERROR "p escapes to heap$"
    59  }
    60  
    61  // in -> in
    62  type Pair struct {
    63  	p1 *int
    64  	p2 *int
    65  }
    66  
    67  func param3(p *Pair) { // ERROR "leaking param content: p$"
    68  	p.p1 = p.p2
    69  }
    70  
    71  func caller3a() {
    72  	i := 0            // ERROR "moved to heap: i$"
    73  	j := 0            // ERROR "moved to heap: j$"
    74  	p := Pair{&i, &j} // ERROR "&i escapes to heap$" "&j escapes to heap$"
    75  	param3(&p)        // ERROR "caller3a &p does not escape"
    76  	_ = p
    77  }
    78  
    79  func caller3b() {
    80  	i := 0            // ERROR "moved to heap: i$"
    81  	j := 0            // ERROR "moved to heap: j$"
    82  	p := Pair{&i, &j} // ERROR "&i escapes to heap$" "&j escapes to heap$"
    83  	param3(&p)        // ERROR "caller3b &p does not escape"
    84  	sink = p          // ERROR "p escapes to heap$"
    85  }
    86  
    87  // in -> rcvr
    88  func (p *Pair) param4(i *int) { // ERROR "\(\*Pair\).param4 p does not escape$" "leaking param: i$"
    89  	p.p1 = i
    90  }
    91  
    92  func caller4a() {
    93  	i := 0 // ERROR "moved to heap: i$"
    94  	p := Pair{}
    95  	p.param4(&i) // ERROR "&i escapes to heap$" "caller4a p does not escape$"
    96  	_ = p
    97  }
    98  
    99  func caller4b() {
   100  	i := 0 // ERROR "moved to heap: i$"
   101  	p := Pair{}
   102  	p.param4(&i) // ERROR "&i escapes to heap$" "caller4b p does not escape$"
   103  	sink = p     // ERROR "p escapes to heap$"
   104  }
   105  
   106  // in -> heap
   107  func param5(i *int) { // ERROR "leaking param: i$"
   108  	sink = i // ERROR "i escapes to heap$"
   109  }
   110  
   111  func caller5() {
   112  	i := 0     // ERROR "moved to heap: i$"
   113  	param5(&i) // ERROR "&i escapes to heap$"
   114  }
   115  
   116  // *in -> heap
   117  func param6(i ***int) { // ERROR "leaking param content: i$"
   118  	sink = *i // ERROR "\*i escapes to heap$"
   119  }
   120  
   121  func caller6a() {
   122  	i := 0      // ERROR "moved to heap: i$"
   123  	p := &i     // ERROR "&i escapes to heap$" "moved to heap: p$"
   124  	p2 := &p    // ERROR "&p escapes to heap$"
   125  	param6(&p2) // ERROR "caller6a &p2 does not escape"
   126  }
   127  
   128  // **in -> heap
   129  func param7(i ***int) { // ERROR "leaking param content: i$"
   130  	sink = **i // ERROR "\* \(\*i\) escapes to heap"
   131  }
   132  
   133  func caller7() {
   134  	i := 0      // ERROR "moved to heap: i$"
   135  	p := &i     // ERROR "&i escapes to heap$" "moved to heap: p$"
   136  	p2 := &p    // ERROR "&p escapes to heap$"
   137  	param7(&p2) // ERROR "caller7 &p2 does not escape"
   138  }
   139  
   140  // **in -> heap
   141  func param8(i **int) { // ERROR "param8 i does not escape$"
   142  	sink = **i // ERROR "\* \(\*i\) escapes to heap"
   143  }
   144  
   145  func caller8() {
   146  	i := 0
   147  	p := &i    // ERROR "caller8 &i does not escape$"
   148  	param8(&p) // ERROR "caller8 &p does not escape$"
   149  }
   150  
   151  // *in -> out
   152  func param9(p ***int) **int { // ERROR "leaking param: p to result ~r1 level=1"
   153  	return *p
   154  }
   155  
   156  func caller9a() {
   157  	i := 0
   158  	p := &i         // ERROR "caller9a &i does not escape"
   159  	p2 := &p        // ERROR "caller9a &p does not escape"
   160  	_ = param9(&p2) // ERROR "caller9a &p2 does not escape$"
   161  }
   162  
   163  func caller9b() {
   164  	i := 0             // ERROR "moved to heap: i$"
   165  	p := &i            // ERROR "&i escapes to heap$" "moved to heap: p$"
   166  	p2 := &p           // ERROR "&p escapes to heap$"
   167  	sink = param9(&p2) // ERROR "caller9b &p2 does not escape$"  "param9\(&p2\) escapes to heap"
   168  }
   169  
   170  // **in -> out
   171  func param10(p ***int) *int { // ERROR "leaking param: p to result ~r1 level=2"
   172  	return **p
   173  }
   174  
   175  func caller10a() {
   176  	i := 0
   177  	p := &i          // ERROR "caller10a &i does not escape"
   178  	p2 := &p         // ERROR "caller10a &p does not escape"
   179  	_ = param10(&p2) // ERROR "caller10a &p2 does not escape$"
   180  }
   181  
   182  func caller10b() {
   183  	i := 0              // ERROR "moved to heap: i$"
   184  	p := &i             // ERROR "&i escapes to heap$"
   185  	p2 := &p            // ERROR "caller10b &p does not escape$"
   186  	sink = param10(&p2) // ERROR "caller10b &p2 does not escape$" "param10\(&p2\) escapes to heap"
   187  }
   188  
   189  // in escapes to heap (address of param taken and returned)
   190  func param11(i **int) ***int { // ERROR "moved to heap: i$"
   191  	return &i // ERROR "&i escapes to heap$"
   192  }
   193  
   194  func caller11a() {
   195  	i := 0          // ERROR "moved to heap: i"
   196  	p := &i         // ERROR "moved to heap: p" "&i escapes to heap"
   197  	_ = param11(&p) // ERROR "&p escapes to heap"
   198  }
   199  
   200  func caller11b() {
   201  	i := 0             // ERROR "moved to heap: i$"
   202  	p := &i            // ERROR "&i escapes to heap$" "moved to heap: p$"
   203  	sink = param11(&p) // ERROR "&p escapes to heap$" "param11\(&p\) escapes to heap"
   204  }
   205  
   206  func caller11c() { // GOOD
   207  	i := 0              // ERROR "moved to heap: i$"
   208  	p := &i             // ERROR "moved to heap: p" "&i escapes to heap"
   209  	sink = *param11(&p) // ERROR "&p escapes to heap" "\*param11\(&p\) escapes to heap"
   210  }
   211  
   212  func caller11d() {
   213  	i := 0             // ERROR "moved to heap: i$"
   214  	p := &i            // ERROR "&i escapes to heap" "moved to heap: p"
   215  	p2 := &p           // ERROR "&p escapes to heap"
   216  	sink = param11(p2) // ERROR "param11\(p2\) escapes to heap"
   217  }
   218  
   219  // &in -> rcvr
   220  type Indir struct {
   221  	p ***int
   222  }
   223  
   224  func (r *Indir) param12(i **int) { // ERROR "\(\*Indir\).param12 r does not escape$" "moved to heap: i$"
   225  	r.p = &i // ERROR "&i escapes to heap$"
   226  }
   227  
   228  func caller12a() {
   229  	i := 0  // ERROR "moved to heap: i$"
   230  	p := &i // ERROR "&i escapes to heap$" "moved to heap: p$"
   231  	var r Indir
   232  	r.param12(&p) // ERROR "&p escapes to heap$" "caller12a r does not escape$"
   233  	_ = r
   234  }
   235  
   236  func caller12b() {
   237  	i := 0        // ERROR "moved to heap: i$"
   238  	p := &i       // ERROR "&i escapes to heap$" "moved to heap: p$"
   239  	r := &Indir{} // ERROR "caller12b &Indir literal does not escape$"
   240  	r.param12(&p) // ERROR "&p escapes to heap$"
   241  	_ = r
   242  }
   243  
   244  func caller12c() {
   245  	i := 0  // ERROR "moved to heap: i$"
   246  	p := &i // ERROR "&i escapes to heap$" "moved to heap: p$"
   247  	r := Indir{}
   248  	r.param12(&p) // ERROR "&p escapes to heap$" "caller12c r does not escape$"
   249  	sink = r      // ERROR "r escapes to heap$"
   250  }
   251  
   252  func caller12d() {
   253  	i := 0  // ERROR "moved to heap: i$"
   254  	p := &i // ERROR "&i escapes to heap$" "moved to heap: p$"
   255  	r := Indir{}
   256  	r.param12(&p) // ERROR "&p escapes to heap$" "caller12d r does not escape$"
   257  	sink = **r.p  // ERROR "\* \(\*r\.p\) escapes to heap"
   258  }
   259  
   260  // in -> value rcvr
   261  type Val struct {
   262  	p **int
   263  }
   264  
   265  func (v Val) param13(i *int) { // ERROR "Val.param13 v does not escape$" "leaking param: i$"
   266  	*v.p = i
   267  }
   268  
   269  func caller13a() {
   270  	i := 0 // ERROR "moved to heap: i$"
   271  	var p *int
   272  	var v Val
   273  	v.p = &p      // ERROR "caller13a &p does not escape$"
   274  	v.param13(&i) // ERROR "&i escapes to heap$"
   275  	_ = v
   276  }
   277  
   278  func caller13b() {
   279  	i := 0 // ERROR "moved to heap: i$"
   280  	var p *int
   281  	v := Val{&p}  // ERROR "caller13b &p does not escape$"
   282  	v.param13(&i) // ERROR "&i escapes to heap$"
   283  	_ = v
   284  }
   285  
   286  func caller13c() {
   287  	i := 0 // ERROR "moved to heap: i$"
   288  	var p *int
   289  	v := &Val{&p} // ERROR "caller13c &Val literal does not escape$" "caller13c &p does not escape$"
   290  	v.param13(&i) // ERROR "&i escapes to heap$"
   291  	_ = v
   292  }
   293  
   294  func caller13d() {
   295  	i := 0     // ERROR "moved to heap: i$"
   296  	var p *int // ERROR "moved to heap: p$"
   297  	var v Val
   298  	v.p = &p      // ERROR "&p escapes to heap$"
   299  	v.param13(&i) // ERROR "&i escapes to heap$"
   300  	sink = v      // ERROR "v escapes to heap$"
   301  }
   302  
   303  func caller13e() {
   304  	i := 0        // ERROR "moved to heap: i$"
   305  	var p *int    // ERROR "moved to heap: p$"
   306  	v := Val{&p}  // ERROR "&p escapes to heap$"
   307  	v.param13(&i) // ERROR "&i escapes to heap$"
   308  	sink = v      // ERROR "v escapes to heap$"
   309  }
   310  
   311  func caller13f() {
   312  	i := 0        // ERROR "moved to heap: i$"
   313  	var p *int    // ERROR "moved to heap: p$"
   314  	v := &Val{&p} // ERROR "&Val literal escapes to heap$" "&p escapes to heap$"
   315  	v.param13(&i) // ERROR "&i escapes to heap$"
   316  	sink = v      // ERROR "v escapes to heap$"
   317  }
   318  
   319  func caller13g() {
   320  	i := 0 // ERROR "moved to heap: i$"
   321  	var p *int
   322  	v := Val{&p}  // ERROR "caller13g &p does not escape$"
   323  	v.param13(&i) // ERROR "&i escapes to heap$"
   324  	sink = *v.p   // ERROR "\*v\.p escapes to heap"
   325  }
   326  
   327  func caller13h() {
   328  	i := 0 // ERROR "moved to heap: i$"
   329  	var p *int
   330  	v := &Val{&p} // ERROR "caller13h &Val literal does not escape$" "caller13h &p does not escape$"
   331  	v.param13(&i) // ERROR "&i escapes to heap$"
   332  	sink = **v.p  // ERROR "\* \(\*v\.p\) escapes to heap"
   333  }
   334  
   335  type Node struct {
   336  	p *Node
   337  }
   338  
   339  var Sink *Node
   340  
   341  func f(x *Node) { // ERROR "leaking param content: x"
   342  	Sink = &Node{x.p} // ERROR "&Node literal escapes to heap"
   343  }
   344  
   345  func g(x *Node) *Node { // ERROR "leaking param: x to result ~r1 level=0"
   346  	return &Node{x.p} // ERROR "&Node literal escapes to heap"
   347  }
   348  
   349  func h(x *Node) { // ERROR "leaking param: x"
   350  	y := &Node{x} // ERROR "h &Node literal does not escape"
   351  	Sink = g(y)
   352  	f(y)
   353  }