diff options
| author | ArtSin <artsin666@gmail.com> | 2025-08-05 16:39:26 +0400 |
|---|---|---|
| committer | Nobuyoshi Nakada <nobu.nakada@gmail.com> | 2025-08-05 22:19:55 +0900 |
| commit | a6aaeb9acfa47ebfafed051069f7ea870ded4b99 (patch) | |
| tree | 0092499d52ed8af11dda3b9a9120ce893f56814d /load.c | |
| parent | 3d8af5df11e8dba8ccd37b03f9f5b92b2bc66dcb (diff) | |
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.
Diffstat (limited to 'load.c')
| -rw-r--r-- | load.c | 6 |
1 files changed, 3 insertions, 3 deletions
@@ -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)); |
