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 ~r1 level=0$"
   105  	return (*[1]int)(x)
   106  }
   107  
   108  func envForDir(dir string) []string { // ERROR "dir does not escape"
   109  	env := os.Environ()
   110  	return mergeEnvLists([]string{"PWD=" + dir}, env) // ERROR ".PWD=. \+ dir escapes to heap" "\[\]string{...} does not escape"
   111  }
   112  
   113  func mergeEnvLists(in, out []string) []string { // ERROR "leaking param content: in" "leaking param content: out" "leaking param: out to result ~r2 level=0"
   114  NextVar:
   115  	for _, inkv := range in {
   116  		k := strings.SplitAfterN(inkv, "=", 2)[0]
   117  		for i, outkv := range out {
   118  			if strings.HasPrefix(outkv, k) {
   119  				out[i] = inkv
   120  				continue NextVar
   121  			}
   122  		}
   123  		out = append(out, inkv)
   124  	}
   125  	return out
   126  }
   127  
   128  const (
   129  	IPv4len = 4
   130  	IPv6len = 16
   131  )
   132  
   133  var v4InV6Prefix = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}
   134  
   135  func IPv4(a, b, c, d byte) IP {
   136  	p := make(IP, IPv6len) // ERROR "make\(IP, IPv6len\) escapes to heap"
   137  	copy(p, v4InV6Prefix)
   138  	p[12] = a
   139  	p[13] = b
   140  	p[14] = c
   141  	p[15] = d
   142  	return p
   143  }
   144  
   145  type IP []byte
   146  
   147  type IPAddr struct {
   148  	IP   IP
   149  	Zone string // IPv6 scoped addressing zone
   150  }
   151  
   152  type resolveIPAddrTest struct {
   153  	network       string
   154  	litAddrOrName string
   155  	addr          *IPAddr
   156  	err           error
   157  }
   158  
   159  var resolveIPAddrTests = []resolveIPAddrTest{
   160  	{"ip", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
   161  	{"ip4", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
   162  	{"ip4:icmp", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
   163  }
   164  
   165  func setupTestData() {
   166  	resolveIPAddrTests = append(resolveIPAddrTests,
   167  		[]resolveIPAddrTest{ // ERROR "\[\]resolveIPAddrTest{...} does not escape"
   168  			{"ip",
   169  				"localhost",
   170  				&IPAddr{IP: IPv4(127, 0, 0, 1)}, // ERROR "&IPAddr{...} escapes to heap"
   171  				nil},
   172  			{"ip4",
   173  				"localhost",
   174  				&IPAddr{IP: IPv4(127, 0, 0, 1)}, // ERROR "&IPAddr{...} escapes to heap"
   175  				nil},
   176  		}...)
   177  }
   178  

View as plain text