Bug #22468
openA read of a class variable after remove_class_variable returns a broken value, then SEGV on use
Description
Description¶
A method that read a class variable once reads it again after remove_class_variable. The second read does not raise NameError. It returns a broken value, and a use of that value causes a segmentation fault.
Steps to reproduce¶
Expected result¶
The second C.x raises NameError, as Ruby 2.7.8 does:
Actual result¶
test.rb:9: [BUG] Segmentation fault at 0x0000000000000034
ruby 4.0.9 (2026-10-23 revision 3e93b23afc) +PRISM [x86_64-linux]
The C level backtrace stops in flo_to_s (rb_float_noflonum_value, internal/numeric.h:287), which p calls through rb_inspect.
Notes¶
-
Without the first
C.x(line 7), the secondC.xraises NameError correctly. So the inline cache of the class variable read can keep the removed entry. -
The read itself does not crash.
p C.x.classprintsFloat, so the read returns a broken value with no error. The crash comes when the program uses the value. -
With
@@x = []andGC.startbefore the second read, the crash is the same. -
--yjitand--zjitgive the same SEGV. With--yjit --yjit-call-threshold=1or--zjit --zjit-call-threshold=1,p C.xprintsmain, and then Ruby stops with a different bug:
Versions¶
| Version | Result |
|---|---|
| ruby 2.7.8 | NameError (correct) |
| ruby 3.4.12 (2026-10-23 revision 366f5fdc00) | SEGV |
| ruby 4.0.9 (2026-10-23 revision 3e93b23afc) | SEGV |
| ruby 4.1.0dev (2026-10-24T08:43:21Z master e6403ebc10) | SEGV |
Platform: x86_64-linux (Ubuntu 24.04).
Updated by jeremyevans0 (Jeremy Evans) about 12 hours ago
In case it assists debugging, the example works correctly in Ruby 3.0 and 3.1 (NameError) and fails in Ruby 3.2 and 3.3 (SEGV). So it broke between Ruby 3.1 and 3.2.