From a6aaeb9acfa47ebfafed051069f7ea870ded4b99 Mon Sep 17 00:00:00 2001 From: ArtSin Date: Tue, 5 Aug 2025 16:39:26 +0400 Subject: load.c: fix `prev_ext_config` clobbering in `require_internal` The variable `prev_ext_config` is modified by `ext_config_push` between `setjmp` and `longjmp` calls. Since `ext_config_push` and `ext_config_pop` are small and likely to be inlined, `prev_ext_config` can be allocated on a register and get clobbered. Fix by making it `volatile`. This bug can be observed by adding a check for values greater than 1 in `th2->ext_config.ractor_safe` after `ext_config_pop` and building with Clang. --- load.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'load.c') diff --git a/load.c b/load.c index 329b0f4b3b..017c236483 100644 --- a/load.c +++ b/load.c @@ -1346,14 +1346,14 @@ rb_resolve_feature_path(VALUE klass, VALUE fname) } static void -ext_config_push(rb_thread_t *th, struct rb_ext_config *prev) +ext_config_push(rb_thread_t *th, volatile struct rb_ext_config *prev) { *prev = th->ext_config; th->ext_config = (struct rb_ext_config){0}; } static void -ext_config_pop(rb_thread_t *th, struct rb_ext_config *prev) +ext_config_pop(rb_thread_t *th, volatile struct rb_ext_config *prev) { th->ext_config = *prev; } @@ -1407,7 +1407,7 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool wa VALUE realpaths = get_loaded_features_realpaths(vm_ns); VALUE realpath_map = get_loaded_features_realpath_map(vm_ns); volatile bool reset_ext_config = false; - struct rb_ext_config prev_ext_config; + volatile struct rb_ext_config prev_ext_config; path = rb_str_encode_ospath(fname); RUBY_DTRACE_HOOK(REQUIRE_ENTRY, RSTRING_PTR(fname)); -- cgit v1.2.3