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