From 6b35f074bd83794007d4c7b773a289bddef0dbdf Mon Sep 17 00:00:00 2001 From: Satoshi Tagomori Date: Tue, 16 Dec 2025 22:17:08 +0900 Subject: [PATCH 1/5] Box: [DOC] Add RUBY_BOX in Environment --- man/ruby.1 | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/man/ruby.1 b/man/ruby.1 index d19cea99ca3c5b..8141a6d7efa97a 100644 --- a/man/ruby.1 +++ b/man/ruby.1 @@ -523,6 +523,13 @@ variable is not defined, Ruby refers to If set, Ruby tries to free all dynamically allocated memories. Introduced in Ruby 3.3, default: unset. .Pp +.It Ev RUBY_BOX +If set to +.Li 1 , +Ruby Box is enabled and users will be able to execute +.Li Ruby::Box.new . +Ruby Box is an experimental feature introduced in Ruby 4.0. +.Pp .It Ev RUBY_IO_BUFFER_DEFAULT_SIZE The custom default buffer size of .Li IO::Buffer . From 09a29e1312121fed5704ac196413c3b5ecb83fd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Barri=C3=A9?= Date: Tue, 16 Dec 2025 17:06:33 +0100 Subject: [PATCH 2/5] Add the class variable and the class itself in Ractor::IsolationError (#15562) --- bootstraptest/test_ractor.rb | 4 ++-- variable.c | 13 ++++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index 6b35bbb46be896..2b268e9966d076 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -1022,7 +1022,7 @@ def initialize } # cvar in shareable-objects are not allowed to access from non-main Ractor -assert_equal 'can not access class variables from non-main Ractors', %q{ +assert_equal 'can not access class variables from non-main Ractors (@@cv from C)', %q{ class C @@cv = 'str' end @@ -1041,7 +1041,7 @@ class C } # also cached cvar in shareable-objects are not allowed to access from non-main Ractor -assert_equal 'can not access class variables from non-main Ractors', %q{ +assert_equal 'can not access class variables from non-main Ractors (@@cv from C)', %q{ class C @@cv = 'str' def self.cv diff --git a/variable.c b/variable.c index 47b521856676dd..a1899274725229 100644 --- a/variable.c +++ b/variable.c @@ -1195,10 +1195,13 @@ IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(ID id) } } -#define CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR() \ - if (UNLIKELY(!rb_ractor_main_p())) { \ - rb_raise(rb_eRactorIsolationError, "can not access class variables from non-main Ractors"); \ - } +static void +CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(VALUE klass, ID id) +{ + if (UNLIKELY(!rb_ractor_main_p())) { + rb_raise(rb_eRactorIsolationError, "can not access class variables from non-main Ractors (%"PRIsVALUE" from %"PRIsVALUE")", rb_id2str(id), klass); + } +} static inline void ivar_ractor_check(VALUE obj, ID id) @@ -4202,7 +4205,7 @@ cvar_overtaken(VALUE front, VALUE target, ID id) } #define CVAR_LOOKUP(v,r) do {\ - CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(); \ + CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(klass, id); \ if (cvar_lookup_at(klass, id, (v))) {r;}\ CVAR_FOREACH_ANCESTORS(klass, v, r);\ } while(0) From aab4f6287da4d8035035f7486072f149abf8dcc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Barri=C3=A9?= Date: Tue, 16 Dec 2025 17:47:13 +0100 Subject: [PATCH 3/5] Add the instance variable name and the module in Ractor::IsolationError (#15563) --- bootstraptest/test_ractor.rb | 2 +- variable.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index 2b268e9966d076..575b96e48d501a 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -846,7 +846,7 @@ def ractor_local_globals } # ivar in shareable-objects are not allowed to access from non-main Ractor -assert_equal "can not get unshareable values from instance variables of classes/modules from non-main Ractors", <<~'RUBY', frozen_string_literal: false +assert_equal "can not get unshareable values from instance variables of classes/modules from non-main Ractors (@iv from C)", <<~'RUBY', frozen_string_literal: false class C @iv = 'str' end diff --git a/variable.c b/variable.c index a1899274725229..7a015a51e397e0 100644 --- a/variable.c +++ b/variable.c @@ -1447,7 +1447,8 @@ rb_ivar_lookup(VALUE obj, ID id, VALUE undef) UNLIKELY(!rb_ractor_main_p()) && !rb_ractor_shareable_p(val)) { rb_raise(rb_eRactorIsolationError, - "can not get unshareable values from instance variables of classes/modules from non-main Ractors"); + "can not get unshareable values from instance variables of classes/modules from non-main Ractors (%"PRIsVALUE" from %"PRIsVALUE")", + rb_id2str(id), obj); } return val; } From a8ba2b295b73a116d24fe5602d892d4a2042cd08 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 16 Dec 2025 09:15:46 -0800 Subject: [PATCH 4/5] add 21254 to the feature list --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index 4b16fd50189d0b..465f8ec4b204a8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -456,6 +456,7 @@ A lot of work has gone into making Ractors more stable, performant, and usable. [Feature #21205]: https://bugs.ruby-lang.org/issues/21205 [Feature #21216]: https://bugs.ruby-lang.org/issues/21216 [Feature #21219]: https://bugs.ruby-lang.org/issues/21219 +[Feature #21254]: https://bugs.ruby-lang.org/issues/21254 [Feature #21258]: https://bugs.ruby-lang.org/issues/21258 [Feature #21262]: https://bugs.ruby-lang.org/issues/21262 [Feature #21275]: https://bugs.ruby-lang.org/issues/21275 From d209e6f1c0a93ad3ce1cc64dd165a6b67672614d Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Wed, 26 Nov 2025 21:59:37 -0500 Subject: [PATCH 5/5] search_nonascii(): Replace UB pointer cast with memcpy Casting a pointer to create an unaligned one is undefined behavior in C standards. Use memcpy to express the unaligned load instead to play by the rules. Practically, this yields the same binary output in many situations while fixing the crash in [Bug #21715]. --- string.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/string.c b/string.c index 060a1467a06f55..9819a5910fa76e 100644 --- a/string.c +++ b/string.c @@ -716,7 +716,7 @@ VALUE rb_fs; static inline const char * search_nonascii(const char *p, const char *e) { - const uintptr_t *s, *t; + const char *s, *t; #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) # if SIZEOF_UINTPTR_T == 8 @@ -760,17 +760,19 @@ search_nonascii(const char *p, const char *e) #define aligned_ptr(value) \ __builtin_assume_aligned((value), sizeof(uintptr_t)) #else -#define aligned_ptr(value) (uintptr_t *)(value) +#define aligned_ptr(value) (value) #endif s = aligned_ptr(p); - t = (uintptr_t *)(e - (SIZEOF_VOIDP-1)); + t = (e - (SIZEOF_VOIDP-1)); #undef aligned_ptr - for (;s < t; s++) { - if (*s & NONASCII_MASK) { + for (;s < t; s += sizeof(uintptr_t)) { + uintptr_t word; + memcpy(&word, s, sizeof(word)); + if (word & NONASCII_MASK) { #ifdef WORDS_BIGENDIAN - return (const char *)s + (nlz_intptr(*s&NONASCII_MASK)>>3); + return (const char *)s + (nlz_intptr(word&NONASCII_MASK)>>3); #else - return (const char *)s + (ntz_intptr(*s&NONASCII_MASK)>>3); + return (const char *)s + (ntz_intptr(word&NONASCII_MASK)>>3); #endif } }