Source file test/escape_slice.go

     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 slices.
     8  
     9  package escape
    10  
    11  import (
    12  	"os"
    13  	"strings"
    14  )
    15  
    16  var sink interface{}
    17  
    18  func slice0() {
    19  	var s []*int
    20  	// BAD: i should not escape
    21  	i := 0 // ERROR "moved to heap: i"
    22  	s = append(s, &i)
    23  	_ = s
    24  }
    25  
    26  func slice1() *int {
    27  	var s []*int
    28  	i := 0 // ERROR "moved to heap: i"
    29  	s = append(s, &i)
    30  	return s[0]
    31  }
    32  
    33  func slice2() []*int {
    34  	var s []*int
    35  	i := 0 // ERROR "moved to heap: i"
    36  	s = append(s, &i)
    37  	return s
    38  }
    39  
    40  func slice3() *int {
    41  	var s []*int
    42  	i := 0 // ERROR "moved to heap: i"
    43  	s = append(s, &i)
    44  	for _, p := range s {
    45  		return p
    46  	}
    47  	return nil
    48  }
    49  
    50  func slice4(s []*int) { // ERROR "s does not escape"
    51  	i := 0 // ERROR "moved to heap: i"
    52  	s[0] = &i
    53  }
    54  
    55  func slice5(s []*int) { // ERROR "s does not escape"
    56  	if s != nil {
    57  		s = make([]*int, 10) // ERROR "make\(\[\]\*int, 10\) does not escape"
    58  	}
    59  	i := 0 // ERROR "moved to heap: i"
    60  	s[0] = &i
    61  }
    62  
    63  func slice6() {
    64  	s := make([]*int, 10) // ERROR "make\(\[\]\*int, 10\) does not escape"
    65  	// BAD: i should not escape
    66  	i := 0 // ERROR "moved to heap: i"
    67  	s[0] = &i
    68  	_ = s
    69  }
    70  
    71  func slice7() *int {
    72  	s := make([]*int, 10) // ERROR "make\(\[\]\*int, 10\) does not escape"
    73  	i := 0                // ERROR "moved to heap: i"
    74  	s[0] = &i
    75  	return s[0]
    76  }
    77  
    78  func slice8() {
    79  	i := 0
    80  	s := []*int{&i} // ERROR "\[\]\*int{...} does not escape"
    81  	_ = s
    82  }
    83  
    84  func slice9() *int {
    85  	i := 0          // ERROR "moved to heap: i"
    86  	s := []*int{&i} // ERROR "\[\]\*int{...} does not escape"
    87  	return s[0]
    88  }
    89  
    90  func slice10() []*int {
    91  	i := 0          // ERROR "moved to heap: i"
    92  	s := []*int{&i} // ERROR "\[\]\*int{...} escapes to heap"
    93  	return s
    94  }
    95  
    96  func slice11() {
    97  	i := 2
    98  	s := make([]int, 2, 3) // ERROR "make\(\[\]int, 2, 3\) does not escape"
    99  	s = make([]int, i, 3)  // ERROR "make\(\[\]int, i, 3\) does not escape"
   100  	s = make([]int, i, 1)  // ERROR "make\(\[\]int, i, 1\) does not escape"
   101  	_ = s
   102  }
   103  
   104  func slice12(x []int) *[1]int { // ERROR "leaking param: x to result ~r0 level=0$"
   105  	return (*[1]int)(x)
   106  }
   107  
   108  func slice13(x []*int) [1]*int { // ERROR "leaking param: x to result ~r0 level=1$"
   109  	return [1]*int(x)
   110  }
   111  
   112  func envForDir(dir string) []string { // ERROR "dir does not escape"
   113  	env := os.Environ()
   114  	return mergeEnvLists([]string{"PWD=" + dir}, env) // ERROR ".PWD=. \+ dir escapes to heap" "\[\]string{...} does not escape"
   115  }
   116  
   117  func mergeEnvLists(in, out []string) []string { // ERROR "leaking param content: in" "leaking param content: out" "leaking param: out to result ~r0 level=0"
   118  NextVar:
   119  	for _, inkv := range in {
   120  		k := strings.SplitAfterN(inkv, "=", 2)[0]
   121  		for i, outkv := range out {
   122  			if strings.HasPrefix(outkv, k) {
   123  				out[i] = inkv
   124  				continue NextVar
   125  			}
   126  		}
   127  		out = append(out, inkv)
   128  	}
   129  	return out
   130  }
   131  
   132  const (
   133  	IPv4len = 4
   134  	IPv6len = 16
   135  )
   136  
   137  var v4InV6Prefix = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}
   138  
   139  func IPv4(a, b, c, d byte) IP {
   140  	p := make(IP, IPv6len) // ERROR "make\(IP, 16\) escapes to heap"
   141  	copy(p, v4InV6Prefix)
   142  	p[12] = a
   143  	p[13] = b
   144  	p[14] = c
   145  	p[15] = d
   146  	return p
   147  }
   148  
   149  type IP []byte
   150  
   151  type IPAddr struct {
   152  	IP   IP
   153  	Zone string // IPv6 scoped addressing zone
   154  }
   155  
   156  type resolveIPAddrTest struct {
   157  	network       string
   158  	litAddrOrName string
   159  	addr          *IPAddr
   160  	err           error
   161  }
   162  
   163  var resolveIPAddrTests = []resolveIPAddrTest{
   164  	{"ip", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
   165  	{"ip4", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
   166  	{"ip4:icmp", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
   167  }
   168  
   169  func setupTestData() {
   170  	resolveIPAddrTests = append(resolveIPAddrTests,
   171  		[]resolveIPAddrTest{ // ERROR "\[\]resolveIPAddrTest{...} does not escape"
   172  			{"ip",
   173  				"localhost",
   174  				&IPAddr{IP: IPv4(127, 0, 0, 1)}, // ERROR "&IPAddr{...} escapes to heap"
   175  				nil},
   176  			{"ip4",
   177  				"localhost",
   178  				&IPAddr{IP: IPv4(127, 0, 0, 1)}, // ERROR "&IPAddr{...} escapes to heap"
   179  				nil},
   180  		}...)
   181  }
   182  

View as plain text