Project

General

Profile

« Previous | Next » 

Revision e23a60b9

Added by peterzhu2118 (Peter Zhu) 7 months ago

Fix GC compaction crash when using local variables in eval

If we have local variables outside of the eval, the local variables names
are IDs. We convert these IDs to char * using rb_id2name. However, these
char * are actually Ruby strings, which may be embedded. This means that
it is not safe to rb_id2name and call any potential GC entrypoints because
if a GC compaction runs, the embedded string may move and the pointer will
change.

For example, if you compile with -DRGENGC_CHECK_MODE=1, then the following
script will crash:

GC.auto_compact = :empty
GC.stress = true

o = Object.new

eval("def o.m(k: 0) k end")

The crash message is:

test.rb:6: [BUG] Local with constant_id 1 does not exist
ruby 3.4.0dev (2024-12-17T18:34:57Z prism-local-compac.. 434346726c) +PRISM [arm64-darwin24]

-- C level backtrace information -------------------------------------------
miniruby(rb_print_backtrace+0x24) [0x10312fec4] vm_dump.c:823
miniruby(rb_print_backtrace) (null):0
miniruby(rb_vm_bugreport+0x2d4) [0x1031301b8] vm_dump.c:1155
miniruby(rb_bug_without_die_internal+0xa8) [0x102dd6a94] error.c:1097
miniruby(rb_bug+0x28) [0x102dd6b00] error.c:1115
miniruby(pm_lookup_local_index+0xec) [0x102d61e4c] prism_compile.c:1237
miniruby(pm_compile_node+0x45d0) [0x102d252f4] prism_compile.c:9334
miniruby(pm_compile_node+0x1864) [0x102d22588] prism_compile.c:8650
miniruby(pm_compile_node+0x65ec) [0x102d27310] prism_compile.c:9897
miniruby(pm_compile_scope_node+0x3008) [0x102d77bcc] prism_compile.c:6584
miniruby(pm_compile_node+0x5ec4) [0x102d26be8] prism_compile.c:9768
miniruby(pm_iseq_compile_node+0xac) [0x102d20bf0] prism_compile.c:10069
miniruby(pm_iseq_new_with_opt_try+0x2c) [0x102e7d088] iseq.c:1029
miniruby(rb_protect+0x108) [0x102dea9bc] eval.c:1033
miniruby(pm_iseq_new_with_opt+0x264) [0x102e7c444] iseq.c:1082
miniruby(pm_iseq_new_eval+0xec) [0x102e7c8e0] iseq.c:961
miniruby(pm_eval_make_iseq+0x594) [0x1031209cc] vm_eval.c:1770
miniruby(eval_make_iseq+0x54) [0x103120068] vm_eval.c:1799