-
Notifications
You must be signed in to change notification settings - Fork 175
Prism parser crashes in WASM (wasm32-wasi): pm_parser_init out-of-bounds memory access #4065
Description
Summary
When Ruby 3.4 or 4.0 is compiled to WebAssembly (wasm32-wasi) with Prism as the default parser, string-based eval and class_eval calls crash with an out-of-bounds memory access in pm_parser_init.
Building with --with-parser=parse.y and overriding RB_DEFAULT_PARSER to RB_DEFAULT_PARSER_PARSE_Y avoids the crash.
This issue is filed to investigate whether pm_parser_init has a WASM-specific bug. The parse.y workaround is a temporary measure; ideally Prism should work correctly in WASM environments without requiring a parser downgrade.
Environment
- Ruby: 3.4.8 / 4.0.2 (compiled to wasm32-unknown-wasip1 via ruby_wasm 2.9.0)
- wasi_sdk: 24.0
- WASM runtime: wasmtime
Steps to reproduce
- Build Ruby 3.4 or 4.0 for WASM with the default Prism parser
- Run
wasmtime run ruby-core.wasm -e 'eval("puts \"hello\"")'
Observed behaviour
The process crashes with exit code 134 (SIGABRT):
Error: failed to run main module ruby-core.wasm
...
ruby!pm_parser_init
ruby!pm_parse_string
ruby!eval_make_iseq
ruby!eval_string_with_cref
ruby!specific_eval
ruby!rb_mod_module_eval_internal
...
memory fault at wasm address 0xfffffffc in linear memory of size 0xffd30000
wasm trap: out of bounds memory access
The crash occurs in the call chain:
rb_mod_module_eval_internal → specific_eval → eval_string_with_cref → eval_make_iseq → pm_parse_string → pm_parser_init.
Ruby 3.3 (which uses parse.y by default) does not exhibit this crash.
Note that puts "hello" without eval does not crash; the issue is specific to string-based eval paths that invoke Prism.
Workaround
Forcing the parse.y parser avoids the crash. Two changes are needed:
- Source patch (
version.c): overrideRB_DEFAULT_PARSERto
RB_DEFAULT_PARSER_PARSE_Y - Build flag: pass
--with-parser=parse.ytoconfigure
Patch file:
https://github.com/aim2bpg/rubree/blob/main/ruby_wasm_patches/fix-default-parser-parse-y.patch
With this workaround applied, Ruby 3.4.8 and 4.0.2 boot and run successfully in WASM (verified with a Rails 8.1.3 application).
Note: this is a temporary workaround for WASM environments only and has no effect on native Ruby builds.
Related
- Seems to be a compatibility issue with Ruby 3.4 palkan/wasmify-rails#7 — another Ruby 3.4 WASM incompatibility (different
root cause: missing C extension)