Skip to content

Detect large fixed-size arrays that would overflow goroutine stacks #5

@drpaneas

Description

@drpaneas

Problem

In libgodc, spawned goroutines get fixed 64KB stacks and the main goroutine gets 128KB. There is no stack growth and no overflow detection (see #4).

A fixed-size array local variable that doesn't escape will be placed entirely on the stack by the compiler:

func loadLevel() {
    var buf [100000]byte  // 100KB on stack - overflows 64KB goroutine stack
    // ...
}

This silently overflows the stack and corrupts adjacent memory. The developer gets no warning at compile time or runtime.

Note that make([]byte, 100000) is safe - make always heap-allocates the backing array through gc_alloc, which routes large objects (>64KB) to malloc(). Only fixed-size arrays are at risk.

Possible solutions

1. Compile-time detection

Add a lint or build step that scans Go source for fixed-size array declarations and warns when the total size of local arrays in a function approaches the stack limit. Could use go vet-style analysis or gccgo's -fgo-dump-escape output to identify stack-allocated large arrays.

2. Compiler flag for max stack frame size

gccgo/GCC has -Wframe-larger-than=N which warns when a function's stack frame exceeds N bytes. Setting -Wframe-larger-than=32768 (half the goroutine stack, leaving room for call depth) would catch the obvious cases at compile time.

3. Runtime canary check

As proposed in #4, a stack canary at the bottom of each goroutine's stack would detect overflow after the fact (at yield/GC points).

4. Documentation

At minimum, document this pitfall clearly: use make for large buffers, keep fixed-size arrays well under the stack size.

Action items

  • Test if -Wframe-larger-than=N works with gccgo for Go source (it may only apply to C)
  • If not, explore a build-time linter that checks array sizes in Go functions
  • Add guidance to effective-dreamcast-go.md about fixed-size arrays vs make
  • Consider adding a canary check (ties into Investigate stack overflow detection without split-stack prologues #4)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions