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 9package escape 10 11import ( 12 "os" 13 "strings" 14) 15 16var sink interface{} 17 18func 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 26func 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 33func slice2() []*int { 34 var s []*int 35 i := 0 // ERROR "moved to heap: i" 36 s = append(s, &i) 37 return s 38} 39 40func 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 50func slice4(s []*int) { // ERROR "s does not escape" 51 i := 0 // ERROR "moved to heap: i" 52 s[0] = &i 53} 54 55func 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 63func 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 71func 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 78func slice8() { 79 i := 0 80 s := []*int{&i} // ERROR "\[\]\*int{...} does not escape" 81 _ = s 82} 83 84func 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 90func slice10() []*int { 91 i := 0 // ERROR "moved to heap: i" 92 s := []*int{&i} // ERROR "\[\]\*int{...} escapes to heap" 93 return s 94} 95 96func 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 104func slice12(x []int) *[1]int { // ERROR "leaking param: x to result ~r0 level=0$" 105 return (*[1]int)(x) 106} 107 108func slice13(x []*int) [1]*int { // ERROR "leaking param: x to result ~r0 level=1$" 109 return [1]*int(x) 110} 111 112func 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 117func mergeEnvLists(in, out []string) []string { // ERROR "leaking param content: in" "leaking param content: out" "leaking param: out to result ~r0 level=0" 118NextVar: 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 132const ( 133 IPv4len = 4 134 IPv6len = 16 135) 136 137var v4InV6Prefix = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff} 138 139func 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 149type IP []byte 150 151type IPAddr struct { 152 IP IP 153 Zone string // IPv6 scoped addressing zone 154} 155 156type resolveIPAddrTest struct { 157 network string 158 litAddrOrName string 159 addr *IPAddr 160 err error 161} 162 163var 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 169func 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