vm_eval.c: Preserve rb_iterate0 locals across longjmp

Clang 17 at -O1 with -fPIC can incorrectly rematerialize cfp after longjmp when a nearby stack layout changes, even though cfp is not modified in the tag region. This makes rb_iterate0 miss the matching escape frame and propagate TAG_BREAK as an unexpected break.

Copy the ec argument into a volatile local and make the saved cfp volatile so both values are reloaded from their pre-setjmp storage. This keeps the direct ZJIT fields added by #17953.

This is the rb_iterate0 portion of #17931.
This commit is contained in:
Takashi Kokubun 2026-07-21 17:33:01 -04:00
parent 49cc7e3403
commit 156b4794e3
Notes: git 2026-07-22 07:02:00 +00:00

View File

@ -1479,11 +1479,12 @@ vm_frametype_name(const rb_control_frame_t *cfp);
static VALUE
rb_iterate0(VALUE (* it_proc) (VALUE), VALUE data1,
const struct vm_ifunc *const ifunc,
rb_execution_context_t *ec)
rb_execution_context_t *ec_arg)
{
enum ruby_tag_type state;
volatile VALUE retval = Qnil;
rb_control_frame_t *const cfp = ec->cfp;
rb_execution_context_t * volatile ec = ec_arg;
rb_control_frame_t *volatile const cfp = ec->cfp;
EC_PUSH_TAG(ec);
state = EC_EXEC_TAG();