Skip to content

wit-bindgen-go hangs on deeply nested result types #410

@kavoc-brown

Description

@kavoc-brown

Summary

wit-bindgen-go generate hangs and is eventually killed (SIGTERM) when processing a legal WIT package that contains a very deeply nested result<_, result<_, list<...>>> shape.

Steps-To-Reproduce

ulimit -Sv 4194304 # 4GB virtual mem cap
go run ./cmd/wit-bindgen-go \
  generate \
  --versioned \
  --generate-wit \
  --out .poc_out \
  poc.wit

poc.wit (validated by wasm-tools component wit)

package x:name5;

interface name1 {
}

interface name2 {
}

interface name3 {
}

interface name4 {
}

interface name5 {
}

interface name6 {
}

interface name7 {
}

interface name8 {
}

interface name9 {
}

world name {
  import name2:name3/x@1.1.0+1.2.0;
  use name2:name3/x@1.1.0+1.2.0.{name5 as name};

  type name2 = tuple<list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, bool>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>, bool, bool, bool, bool, bool>;

  type name3 = result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>;

  flags name4 {
    name5,
    name6,
    name7,
    name8,
    name9,
    name10,
    name11,
    name12,
    name13,
  }

  type name14 = tuple<list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, bool>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>, bool, bool, bool, bool, bool>;

  record name15 {
    name16: bool,
  }

  export name2:name3/x@1.1.0+1.2.0;
}
package name2:name3@1.1.0+1.2.0 {
  interface x {
    type name8 = result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>;

    enum name12 {
      name13,
      name14,
    }

    type name10 = result<char, result<result<char, result<result<char, result<result<char, result<result<char, result<result<char, result<result<char, result<result<char, result<result<char, result<result<char, result<result<char, result<result<char, result<result<char, result<result<char, result<f32>>>>>>>>>>>>>>>>>>>>>>>>>>>>;

    type name3 = result<char, result<result<char, result<result<char, result<result<char, result<result<char, result<result<char, result<result<char, result<result<char, result<result<char, result<result<char, result<result<char, result<result<char, result<result<char, result<result<char, result<f32>>>>>>>>>>>>>>>>>>>>>>>>>>>>;

    enum name5 {
      name6,
      name7,
    }

    name2: func(name: result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>, name1: bool, name2: bool, name3: bool);

    name: async func(name: tuple<f32, tuple<result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<bool>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>, bool>>) -> tuple<result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>, bool>;

    name9: func(name: result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, list<result<_, result<_, u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>, name1: bool, name2: bool, name3: bool);

    x11: func();

    x: func();
  }
}

Expected

writes generated Go bindings successfully.

Actual

process spins until killed (OOM).

Environment

ubuntu 22.04, x86-64, Go 1.24.3

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions