From 98603ce8ccbf5ab21d562d5838444c8683b3c133 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Thu, 29 Jan 2026 20:48:08 +0100 Subject: [PATCH 1/2] RB_GC_GUARD() the VALUE for RSTRING_PTR() to ensure the char* does not move * See https://github.com/ruby/prism/pull/3886#discussion_r2741579984. --- ext/prism/extension.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/ext/prism/extension.c b/ext/prism/extension.c index cde10bf360..ecfc960d61 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -201,12 +201,16 @@ build_options_i(VALUE key, VALUE value, VALUE argument) { const char *version = check_string(value); if (RSTRING_LEN(value) == 7 && strncmp(version, "current", 7) == 0) { - const char *ruby_version = RSTRING_PTR(rb_const_get(rb_cObject, rb_intern("RUBY_VERSION"))); + VALUE ruby_version_string = rb_const_get(rb_cObject, rb_intern("RUBY_VERSION")); + const char *ruby_version = RSTRING_PTR(ruby_version_string); if (!pm_options_version_set(options, ruby_version, 3)) { - rb_exc_raise(rb_exc_new_cstr(rb_cPrismCurrentVersionError, ruby_version)); + rb_exc_raise(rb_exc_new_str(rb_cPrismCurrentVersionError, ruby_version_string)); } + + RB_GC_GUARD(ruby_version_string); // Do not move ruby_version while running the code above } else if (RSTRING_LEN(value) == 7 && strncmp(version, "nearest", 7) == 0) { - const char *ruby_version = RSTRING_PTR(rb_const_get(rb_cObject, rb_intern("RUBY_VERSION"))); + VALUE ruby_version_string = rb_const_get(rb_cObject, rb_intern("RUBY_VERSION")); + const char *ruby_version = RSTRING_PTR(ruby_version_string); const char *nearest_version; if (ruby_version[0] < '3' || (ruby_version[0] == '3' && ruby_version[2] < '3')) { @@ -220,6 +224,8 @@ build_options_i(VALUE key, VALUE value, VALUE argument) { if (!pm_options_version_set(options, nearest_version, 3)) { rb_raise(rb_eArgError, "invalid nearest version: %s", nearest_version); } + + RB_GC_GUARD(ruby_version_string); // Do not move ruby_version while running the code above } else if (!pm_options_version_set(options, version, RSTRING_LEN(value))) { rb_raise(rb_eArgError, "invalid version: %" PRIsVALUE, value); } From e30e2591de8f7aa1e118d6f66090b945d58b504d Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Tue, 3 Feb 2026 14:44:30 +0100 Subject: [PATCH 2/2] Directly use `ruby_version` from `ruby/version.h` When I initially wrote this, I used `RUBY_VERSION` so it's easier to stub in tests But turns out that doesn't work in CRuby tests --- ext/prism/extension.c | 10 +--------- ext/prism/extension.h | 1 + 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/ext/prism/extension.c b/ext/prism/extension.c index ecfc960d61..363144970c 100644 --- a/ext/prism/extension.c +++ b/ext/prism/extension.c @@ -201,16 +201,10 @@ build_options_i(VALUE key, VALUE value, VALUE argument) { const char *version = check_string(value); if (RSTRING_LEN(value) == 7 && strncmp(version, "current", 7) == 0) { - VALUE ruby_version_string = rb_const_get(rb_cObject, rb_intern("RUBY_VERSION")); - const char *ruby_version = RSTRING_PTR(ruby_version_string); if (!pm_options_version_set(options, ruby_version, 3)) { - rb_exc_raise(rb_exc_new_str(rb_cPrismCurrentVersionError, ruby_version_string)); + rb_exc_raise(rb_exc_new_cstr(rb_cPrismCurrentVersionError, ruby_version)); } - - RB_GC_GUARD(ruby_version_string); // Do not move ruby_version while running the code above } else if (RSTRING_LEN(value) == 7 && strncmp(version, "nearest", 7) == 0) { - VALUE ruby_version_string = rb_const_get(rb_cObject, rb_intern("RUBY_VERSION")); - const char *ruby_version = RSTRING_PTR(ruby_version_string); const char *nearest_version; if (ruby_version[0] < '3' || (ruby_version[0] == '3' && ruby_version[2] < '3')) { @@ -224,8 +218,6 @@ build_options_i(VALUE key, VALUE value, VALUE argument) { if (!pm_options_version_set(options, nearest_version, 3)) { rb_raise(rb_eArgError, "invalid nearest version: %s", nearest_version); } - - RB_GC_GUARD(ruby_version_string); // Do not move ruby_version while running the code above } else if (!pm_options_version_set(options, version, RSTRING_LEN(value))) { rb_raise(rb_eArgError, "invalid version: %" PRIsVALUE, value); } diff --git a/ext/prism/extension.h b/ext/prism/extension.h index 4ddc3a7b86..a2aaa6388f 100644 --- a/ext/prism/extension.h +++ b/ext/prism/extension.h @@ -5,6 +5,7 @@ #include #include +#include #include "prism.h" VALUE pm_source_new(const pm_parser_t *parser, rb_encoding *encoding, bool freeze);