1// run
2
3// Copyright 2020 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// This test is not for a fix of 29312 proper, but for the patch that
8// makes sure we at least don't have a security hole because of 29312.
9
10// This code generates lots of types. The binary should contain
11// a runtime.slicetype for each of the following 253 types:
12//
13//     []*pwn
14//     [][]*pwn
15//     ...
16//     [][]...[][]*pwn          - 249 total "[]"
17//     [][]...[][][]*pwn        - 250 total "[]"
18//     [][]...[][][][]*pwn      - 251 total "[]"
19//     [][]...[][][][][]*pwn    - 252 total "[]"
20//     [][]...[][][][][][]*pwn  - 253 total "[]"
21//
22// The type names for these types are as follows. Because we truncate
23// the name at depth 250, the last few names are all identical:
24//
25//     type:[]*"".pwn
26//     type:[][]*"".pwn
27//     ...
28//     type:[][]...[][]*pwn       - 249 total "[]"
29//     type:[][]...[][][]*<...>   - 250 total "[]"
30//     type:[][]...[][][][]<...>  - 251 total "[]"
31//     type:[][]...[][][][]<...>  - 252 total "[]" (but only 251 "[]" in the name)
32//     type:[][]...[][][][]<...>  - 253 total "[]" (but only 251 "[]" in the name)
33//
34// Because the names of the last 3 types are all identical, the
35// compiler will generate only a single runtime.slicetype data
36// structure for all 3 underlying types. It turns out the compiler
37// generates just the 251-entry one. There aren't any
38// runtime.slicetypes generated for the final two types.
39//
40// The compiler passes type:[]...[]<...> (251 total "[]") to
41// fmt.Sprintf (instead of the correct 253 one). But the data
42// structure at runtime actually has 253 nesting levels. So we end up
43// calling String on something that is of type [][]*pwn instead of
44// something of type *pwn. The way arg passing in Go works, the
45// backing store pointer for the outer slice becomes the "this"
46// pointer of the String method, which points to the inner []*pwn
47// slice.  The String method then modifies the length of that inner
48// slice.
49package main
50
51import "fmt"
52
53type pwn struct {
54	a [3]uint
55}
56
57func (this *pwn) String() string {
58	this.a[1] = 7 // update length
59	return ""
60}
61
62func main() {
63	var a pwn
64	s := [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]*pwn{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{&a}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} // depth 253
65	fmt.Sprint(s)
66	n := len(s[0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0]) // depth 252, type []*pwn
67	if n != 1 {
68		panic(fmt.Sprintf("length was changed, want 1 got %d", n))
69	}
70}
71