| // run |
| |
| // Copyright 2020 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // This test is not for a fix of 29312 proper, but for the patch that |
| // makes sure we at least don't have a security hole because of 29312. |
| |
| // This code generates lots of types. The binary should contain |
| // a runtime.slicetype for each of the following 253 types: |
| // |
| // []*pwn |
| // [][]*pwn |
| // ... |
| // [][]...[][]*pwn - 249 total "[]" |
| // [][]...[][][]*pwn - 250 total "[]" |
| // [][]...[][][][]*pwn - 251 total "[]" |
| // [][]...[][][][][]*pwn - 252 total "[]" |
| // [][]...[][][][][][]*pwn - 253 total "[]" |
| // |
| // The type names for these types are as follows. Because we truncate |
| // the name at depth 250, the last few names are all identical: |
| // |
| // type.[]*"".pwn |
| // type.[][]*"".pwn |
| // ... |
| // type.[][]...[][]*pwn - 249 total "[]" |
| // type.[][]...[][][]*<...> - 250 total "[]" |
| // type.[][]...[][][][]<...> - 251 total "[]" |
| // type.[][]...[][][][]<...> - 252 total "[]" (but only 251 "[]" in the name) |
| // type.[][]...[][][][]<...> - 253 total "[]" (but only 251 "[]" in the name) |
| // |
| // Because the names of the last 3 types are all identical, the |
| // compiler will generate only a single runtime.slicetype data |
| // structure for all 3 underlying types. It turns out the compiler |
| // generates just the 251-entry one. There aren't any |
| // runtime.slicetypes generated for the final two types. |
| // |
| // The compiler passes type.[]...[]<...> (251 total "[]") to |
| // fmt.Sprintf (instead of the correct 253 one). But the data |
| // structure at runtime actually has 253 nesting levels. So we end up |
| // calling String on something that is of type [][]*pwn instead of |
| // something of type *pwn. The way arg passing in Go works, the |
| // backing store pointer for the outer slice becomes the "this" |
| // pointer of the String method, which points to the inner []*pwn |
| // slice. The String method then modifies the length of that inner |
| // slice. |
| package main |
| |
| import "fmt" |
| |
| type pwn struct { |
| a [3]uint |
| } |
| |
| func (this *pwn) String() string { |
| this.a[1] = 7 // update length |
| return "" |
| } |
| |
| func main() { |
| var a pwn |
| s := [][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]*pwn{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{&a}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} // depth 253 |
| fmt.Sprint(s) |
| 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 |
| if n != 1 { |
| panic(fmt.Sprintf("length was changed, want 1 got %d", n)) |
| } |
| } |