Go version
go version go1.24.3 windows/amd64. Also verified present in tip (b5c2bd7) — src/debug/dwarf/type.go has had no depth-limit changes.
Output of go env in your module/workspace:
GOARCH="amd64"
GOOS="windows"
GOVERSION="go1.24.3"
What did you do?
Called (*dwarf.Data).Type() on a DWARF section containing a long linear chain of DW_TAG_typedef entries, each pointing to the next via DW_AT_type.
package main
import (
"debug/dwarf"
"encoding/binary"
"fmt"
)
func main() {
abbrev := []byte{
0x01, 0x11, 0x01, 0x00, 0x00,
0x02, 0x16, 0x00, 0x49, 0x13, 0x00, 0x00,
0x03, 0x24, 0x00, 0x0b, 0x0b, 0x3e, 0x0b, 0x03, 0x08, 0x00, 0x00,
0x00,
}
const depth = 1_000_000
info := make([]byte, 0, 12+depth*5+8)
var hdr [11]byte
binary.LittleEndian.PutUint32(hdr[:4], uint32(16+depth*5))
binary.LittleEndian.PutUint16(hdr[4:6], 2)
hdr[10] = 4
info = append(info, hdr[:]...)
info = append(info, 0x01)
for i := 0; i < depth; i++ {
info = append(info, 0x02)
var ref [4]byte
if i < depth-1 {
binary.LittleEndian.PutUint32(ref[:], uint32(12+(i+1)*5))
} else {
binary.LittleEndian.PutUint32(ref[:], uint32(12+depth*5))
}
info = append(info, ref[:]...)
}
info = append(info, 0x03, 4, 5, 'i', 'n', 't', 0, 0x00)
d, _ := dwarf.New(abbrev, nil, nil, info, nil, nil, nil, nil)
_, err := d.Type(12)
fmt.Println(err)
}
What did you see happen?
runtime: goroutine stack exceeds 1000000000-byte limit
runtime: sp=0xc020ce1480 stack=[0xc020ce0000, 0xc040ce0000]
fatal error: stack overflow
goroutine 1 [running]:
debug/dwarf.(*Data).readType(...)
.../debug/dwarf/type.go:412
debug/dwarf.(*Data).readType.func3(...)
.../debug/dwarf/type.go:485
debug/dwarf.(*Data).readType(...)
.../debug/dwarf/type.go:809
debug/dwarf.(*Data).readType.func3(...)
.../debug/dwarf/type.go:485
... (repeating)
What did you expect to see?
An error returned, not a fatal crash. readType calls itself recursively through the typeOf closure (type.go:485) with no depth counter. The typeCache map only prevents revisiting the same offset, so it stops cycles but not linear chains of distinct offsets.
go/parser had the same issue fixed in #53616 by adding a nestLev counter. The same approach would work here — add a depth parameter to readType and return a DecodeError when it exceeds a reasonable limit (e.g. 1000).
Go version
go version go1.24.3 windows/amd64. Also verified present in tip (b5c2bd7) —
src/debug/dwarf/type.gohas had no depth-limit changes.Output of
go envin your module/workspace:What did you do?
Called
(*dwarf.Data).Type()on a DWARF section containing a long linear chain ofDW_TAG_typedefentries, each pointing to the next viaDW_AT_type.What did you see happen?
What did you expect to see?
An error returned, not a fatal crash.
readTypecalls itself recursively through thetypeOfclosure (type.go:485) with no depth counter. ThetypeCachemap only prevents revisiting the same offset, so it stops cycles but not linear chains of distinct offsets.go/parserhad the same issue fixed in #53616 by adding anestLevcounter. The same approach would work here — add a depth parameter toreadTypeand return aDecodeErrorwhen it exceeds a reasonable limit (e.g. 1000).