[ruby-core:126353] [Ruby Bug#22237] GC.auto_compact corrupts a String or segfaults from String#tr with dup or gsub
Issue #22237 has been reported by curi (Elliot Temple). ---------------------------------------- Bug #22237: GC.auto_compact corrupts a String or segfaults from String#tr with dup or gsub https://bugs.ruby-lang.org/issues/22237 * Author: curi (Elliot Temple) * Status: Open * ruby -v: ruby 4.0.6 (2026-07-14 revision 03b6d3f889) +YJIT +PRISM [arm64-darwin25] * Backport: 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- `GC.auto_compact = true` can cause memory corruption or segfaults with string methods. Ruby 4.0.6, arm64 macOS, YJIT enabled, 100 runs: 35 clean, 27 corruption, 38 segfault. I also saw the issue with Ruby 4.0.4, x86-64 Debian, or YJIT disabled. ``` ruby # ruby --disable-gems autocompact-test.rb puts RUBY_DESCRIPTION input = "aaa" iterations = Integer(ENV.fetch("ITERATIONS", 10_000_000)) $stdout.sync = true GC.auto_compact = true Object.new # increases chance of memory corruption or segfault iterations.times do |i| s = input.tr("\u0080", "\u20AC").dup # gsub(/x/, "") instead of dup works too # the tr, gsub and dup should all return the original input bytes unless s == input warn "Corrupt output at iteration #{i}: #{s.bytes.inspect}" warn GC.stat.slice(:major_gc_count, :compact_count, :total_moved_objects).inspect exit 2 end end ``` -- https://bugs.ruby-lang.org/
Issue #22237 has been updated by luke-gru (Luke Gruber). Backport changed from 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN to 4.0: REQUIRED Thanks for the good repro, it was very helpful. I have a patch [here](https://github.com/ruby/ruby/pull/18277). ---------------------------------------- Bug #22237: GC.auto_compact corrupts a String or segfaults from String#tr with dup or gsub https://bugs.ruby-lang.org/issues/22237#change-118488 * Author: curi (Elliot Temple) * Status: Open * ruby -v: ruby 4.0.6 (2026-07-14 revision 03b6d3f889) +YJIT +PRISM [arm64-darwin25] * Backport: 4.0: REQUIRED ---------------------------------------- `GC.auto_compact = true` can cause memory corruption or segfaults with string methods. Ruby 4.0.6, arm64 macOS, YJIT enabled, 100 runs: 35 clean, 27 corruption, 38 segfault. I also saw the issue with Ruby 4.0.4, x86-64 Debian, or YJIT disabled. ``` ruby # ruby --disable-gems autocompact-test.rb puts RUBY_DESCRIPTION input = "aaa" iterations = Integer(ENV.fetch("ITERATIONS", 10_000_000)) $stdout.sync = true GC.auto_compact = true Object.new # increases chance of memory corruption or segfault iterations.times do |i| s = input.tr("\u0080", "\u20AC").dup # gsub(/x/, "") instead of dup works too # the tr, gsub and dup should all return the original input bytes unless s == input warn "Corrupt output at iteration #{i}: #{s.bytes.inspect}" warn GC.stat.slice(:major_gc_count, :compact_count, :total_moved_objects).inspect exit 2 end end ``` -- https://bugs.ruby-lang.org/
Issue #22237 has been updated by luke-gru (Luke Gruber). Status changed from Open to Closed This has been fixed by https://github.com/ruby/ruby/commit/9144c914a1a51176d461c06e11bc78723c2c24cb. Backport PR is [here](https://github.com/ruby/ruby/pull/18290). ---------------------------------------- Bug #22237: GC.auto_compact corrupts a String or segfaults from String#tr with dup or gsub https://bugs.ruby-lang.org/issues/22237#change-118507 * Author: curi (Elliot Temple) * Status: Closed * ruby -v: ruby 4.0.6 (2026-07-14 revision 03b6d3f889) +YJIT +PRISM [arm64-darwin25] * Backport: 4.0: REQUIRED ---------------------------------------- `GC.auto_compact = true` can cause memory corruption or segfaults with string methods. Ruby 4.0.6, arm64 macOS, YJIT enabled, 100 runs: 35 clean, 27 corruption, 38 segfault. I also saw the issue with Ruby 4.0.4, x86-64 Debian, or YJIT disabled. ``` ruby # ruby --disable-gems autocompact-test.rb puts RUBY_DESCRIPTION input = "aaa" iterations = Integer(ENV.fetch("ITERATIONS", 10_000_000)) $stdout.sync = true GC.auto_compact = true Object.new # increases chance of memory corruption or segfault iterations.times do |i| s = input.tr("\u0080", "\u20AC").dup # gsub(/x/, "") instead of dup works too # the tr, gsub and dup should all return the original input bytes unless s == input warn "Corrupt output at iteration #{i}: #{s.bytes.inspect}" warn GC.stat.slice(:major_gc_count, :compact_count, :total_moved_objects).inspect exit 2 end end ``` -- https://bugs.ruby-lang.org/
Issue #22237 has been updated by alanwu (Alan Wu). Backport changed from 4.0: REQUIRED to 4.0: DONE Backport PR was merged https://github.com/ruby/ruby/pull/18290 ---------------------------------------- Bug #22237: GC.auto_compact corrupts a String or segfaults from String#tr with dup or gsub https://bugs.ruby-lang.org/issues/22237#change-118585 * Author: curi (Elliot Temple) * Status: Closed * ruby -v: ruby 4.0.6 (2026-07-14 revision 03b6d3f889) +YJIT +PRISM [arm64-darwin25] * Backport: 4.0: DONE ---------------------------------------- `GC.auto_compact = true` can cause memory corruption or segfaults with string methods. Ruby 4.0.6, arm64 macOS, YJIT enabled, 100 runs: 35 clean, 27 corruption, 38 segfault. I also saw the issue with Ruby 4.0.4, x86-64 Debian, or YJIT disabled. ``` ruby # ruby --disable-gems autocompact-test.rb puts RUBY_DESCRIPTION input = "aaa" iterations = Integer(ENV.fetch("ITERATIONS", 10_000_000)) $stdout.sync = true GC.auto_compact = true Object.new # increases chance of memory corruption or segfault iterations.times do |i| s = input.tr("\u0080", "\u20AC").dup # gsub(/x/, "") instead of dup works too # the tr, gsub and dup should all return the original input bytes unless s == input warn "Corrupt output at iteration #{i}: #{s.bytes.inspect}" warn GC.stat.slice(:major_gc_count, :compact_count, :total_moved_objects).inspect exit 2 end end ``` -- https://bugs.ruby-lang.org/
participants (3)
-
alanwu (Alan Wu) -
curi (Elliot Temple) -
luke-gru (Luke Gruber)