Home | History | Annotate | Download | only in test
      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) // ERROR "&i escapes to heap"
     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) // ERROR "&i escapes to heap"
     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) // ERROR "&i escapes to heap"
     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) // ERROR "&i escapes to heap"
     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 // ERROR "&i escapes to heap"
     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 // ERROR "&i escapes to heap"
     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 // ERROR "&i escapes to heap"
     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             // ERROR "&i escapes to heap"
     75 	return s[0]
     76 }
     77 
     78 func slice8() {
     79 	i := 0
     80 	s := []*int{&i} // ERROR "&i does not escape" "literal does not escape"
     81 	_ = s
     82 }
     83 
     84 func slice9() *int {
     85 	i := 0          // ERROR "moved to heap: i"
     86 	s := []*int{&i} // ERROR "&i escapes to heap" "literal 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 "&i escapes to heap" "literal escapes to heap"
     93 	return s
     94 }
     95 
     96 func envForDir(dir string) []string { // ERROR "dir does not escape"
     97 	env := os.Environ()
     98 	return mergeEnvLists([]string{"PWD=" + dir}, env) // ERROR ".PWD=. \+ dir escapes to heap" "\[\]string literal does not escape"
     99 }
    100 
    101 func mergeEnvLists(in, out []string) []string { // ERROR "leaking param content: in" "leaking param content: out" "leaking param: out to result ~r2 level=0"
    102 NextVar:
    103 	for _, inkv := range in {
    104 		k := strings.SplitAfterN(inkv, "=", 2)[0]
    105 		for i, outkv := range out {
    106 			if strings.HasPrefix(outkv, k) {
    107 				out[i] = inkv
    108 				continue NextVar
    109 			}
    110 		}
    111 		out = append(out, inkv)
    112 	}
    113 	return out
    114 }
    115 
    116 const (
    117 	IPv4len = 4
    118 	IPv6len = 16
    119 )
    120 
    121 var v4InV6Prefix = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}
    122 
    123 func IPv4(a, b, c, d byte) IP {
    124 	p := make(IP, IPv6len) // ERROR "make\(IP, IPv6len\) escapes to heap"
    125 	copy(p, v4InV6Prefix)
    126 	p[12] = a
    127 	p[13] = b
    128 	p[14] = c
    129 	p[15] = d
    130 	return p
    131 }
    132 
    133 type IP []byte
    134 
    135 type IPAddr struct {
    136 	IP   IP
    137 	Zone string // IPv6 scoped addressing zone
    138 }
    139 
    140 type resolveIPAddrTest struct {
    141 	network       string
    142 	litAddrOrName string
    143 	addr          *IPAddr
    144 	err           error
    145 }
    146 
    147 var resolveIPAddrTests = []resolveIPAddrTest{
    148 	{"ip", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
    149 	{"ip4", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
    150 	{"ip4:icmp", "127.0.0.1", &IPAddr{IP: IPv4(127, 0, 0, 1)}, nil},
    151 }
    152 
    153 func setupTestData() {
    154 	resolveIPAddrTests = append(resolveIPAddrTests,
    155 		[]resolveIPAddrTest{ // ERROR "\[\]resolveIPAddrTest literal does not escape"
    156 			{"ip",
    157 				"localhost",
    158 				&IPAddr{IP: IPv4(127, 0, 0, 1)}, // ERROR "&IPAddr literal escapes to heap"
    159 				nil},
    160 			{"ip4",
    161 				"localhost",
    162 				&IPAddr{IP: IPv4(127, 0, 0, 1)}, // ERROR "&IPAddr literal escapes to heap"
    163 				nil},
    164 		}...)
    165 }
    166