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 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
113func mergeEnvLists(in, out []string) []string { // ERROR "leaking param content: in" "leaking param content: out" "leaking param: out to result ~r0 level=0"
114NextVar:
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
128const (
129	IPv4len = 4
130	IPv6len = 16
131)
132
133var v4InV6Prefix = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}
134
135func 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
145type IP []byte
146
147type IPAddr struct {
148	IP   IP
149	Zone string // IPv6 scoped addressing zone
150}
151
152type resolveIPAddrTest struct {
153	network       string
154	litAddrOrName string
155	addr          *IPAddr
156	err           error
157}
158
159var 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
165func 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