1 // A reslice past the end of a slice must stay a well-formed view of its
2 // parent: an empty slice, not a slice with a negative length.
3 //
4 // Moxie emits no slice bounds check - the programmer owns the indices - but
5 // `s[1:]` on an empty slice produced len -1, so the tree's
6 // `for ; len(r) > 0; r = r[1:]` loops left `r` with a negative length and the
7 // `if len(r) == 0` guards that follow never fired. A truncated REQ filter
8 // (`{"kinds":[1`) then read past the end and killed the relay.
9 package main
10 11 import (
12 "fmt"
13 "os"
14 )
15 16 func consume(s []byte) (n int32) {
17 for ; len(s) > 0; s = s[1:] {
18 if s[0] == 'x' {
19 return -1
20 }
21 }
22 return int32(len(s))
23 }
24 25 func main() {
26 fmt.Fprintf(os.Stderr, "ok\n")
27 empty := []byte{}
28 after := empty[1:]
29 if len(after) != 0 {
30 panic("reslicing past the end must produce an empty slice")
31 }
32 if consume([]byte("x")) != -1 {
33 panic("the loop body must still see its element")
34 }
35 if consume([]byte("xy")) != -1 {
36 panic("consume must stop at the matching element")
37 }
38 if consume(nil) != 0 {
39 panic("consume of nil must end immediately")
40 }
41 // Extending to capacity is a valid slice, not an out-of-range index.
42 buf := []byte{:0:8}
43 buf = push(buf, 'a', 'b')
44 grown := buf[:cap(buf)]
45 if len(grown) != 8 {
46 panic("reslicing to capacity must keep the capacity")
47 }
48 grown[7] = 'z'
49 if grown[7] != 'z' {
50 panic("the extended view must alias the parent buffer")
51 }
52 // An inverted range and a cursor past the end are both empty. The indices
53 // are variables because a constant inverted range is a frontend error.
54 var lo byte = 3
55 var hi byte = 1
56 inverted := buf[lo:hi]
57 if len(inverted) != 0 {
58 panic("an inverted range must be empty")
59 }
60 past := buf[99:]
61 if len(past) != 0 {
62 panic("a reslice starting past the end must be empty")
63 }
64 // A valid middle slice is unchanged.
65 mid := buf[2:5]
66 if len(mid) != 3 || mid[0] != 0 {
67 panic("a valid sub-slice must keep its bounds")
68 }
69 fmt.Fprintf(os.Stderr, "%d %d %d\n", int32(len(grown)), int32(len(inverted)), int32(len(past)))
70 fmt.Fprintf(os.Stderr, "done\n")
71 }
72