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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions