Project

General

Profile

Bug #21516

Updated by alanwu (Alan Wu) 9 days ago

I noticed segfaults in the test suite of Ruby 3.4.5, related to String#succ! 

 A very easy reproducer is: 

 ``` 
 ./miniruby -e 'puts "ZZZZ999".succ!' 
 ``` 

 ``` 
 $ ./miniruby -e 'puts "ZZZZ999".succ!' 
 -e:1: [BUG] Segmentation fault at 0x9e968041 
 ruby 3.4.5 (2025-07-16 revision 20cda200d3) +PRISM [x86_64-linux-x32] 

 -- Control frame information ----------------------------------------------- 
 c:0003 p:---- s:0011 e:000010 CFUNC    :succ! 
 c:0002 p:0005 s:0007 e:000005 EVAL     -e:1 [FINISH] 
 c:0001 p:0000 s:0003 E:0017b8 DUMMY    [FINISH] 

 -- Ruby level backtrace information ---------------------------------------- 
 -e:1:in '<main>' 
 -e:1:in 'succ!' 

 -- Threading information --------------------------------------------------- 
 Total ractor count: 1 
 Ruby thread count for this ractor: 1 

 -- Machine register context ------------------------------------------------ 
   GS: 0x00000063    FS: 0x00000000    ES: 0x0000002b    DS: 0x0000002b EDI: 0x9e968049 
  ESI: 0x9e968041 EBP: 0x5896c1a0 ESP: 0xff97d638 EBX: 0x9e968046 EDX: 0x9e968049 
  ECX: 0x5896c1a0 EAX: 0x9e968041 TRA: 0x0000000e ERR: 0x00000004 EIP: 0x5681ea07 
   CS: 0x00000023 EFL: 0x00010293 UES: 0xff97d638    SS: 0x0000002b 

 -- C level backtrace information ------------------------------------------- 
 /builddir/ruby/ruby/miniruby(rb_print_backtrace+0x14) [0x568ae631] /builddir/ruby/ruby/vm_dump.c:823 
 /builddir/ruby/ruby/miniruby(rb_vm_bugreport) /builddir/ruby/ruby/vm_dump.c:1155 
 /builddir/ruby/ruby/miniruby(rb_bug_for_fatal_signal+0x86) [0x566e4ee6] /builddir/ruby/ruby/error.c:1130 
 /builddir/ruby/ruby/miniruby(sigsegv+0x4f) [0x5680e98f] /builddir/ruby/ruby/signal.c:934 
 linux-gate.so.1(__kernel_rt_sigreturn+0x0) [0xf7f475a0] 
 /builddir/ruby/ruby/miniruby(search_nonascii+0x17) [0x5681ea07] /builddir/ruby/ruby/string.c:728 
 /builddir/ruby/ruby/miniruby(coderange_scan+0x59) [0x56821d09] /builddir/ruby/ruby/string.c:767 
 /builddir/ruby/ruby/miniruby(rbimpl_fl_unset_raw_raw+0x0) [0x56824715] /builddir/ruby/ruby/string.c:895 
 /builddir/ruby/ruby/miniruby(RB_FL_UNSET_RAW) ./include/ruby/internal/fl_type.h:669 
 /builddir/ruby/ruby/miniruby(RB_ENC_CODERANGE_SET) ./include/ruby/internal/encoding/coderange.h:131 
 /builddir/ruby/ruby/miniruby(rb_enc_str_coderange) /builddir/ruby/ruby/string.c:911 
 /builddir/ruby/ruby/miniruby(str_succ+0x69c) [0x5682545c] /builddir/ruby/ruby/string.c:5364 
 /builddir/ruby/ruby/miniruby(rb_str_succ_bang+0x15) [0x56829f85] /builddir/ruby/ruby/string.c:5380 
 /builddir/ruby/ruby/miniruby(vm_call_cfunc_with_frame_+0x106) [0x568860e6] /builddir/ruby/ruby/vm_insnhelper.c:3794 
 /builddir/ruby/ruby/miniruby(vm_call_method_each_type+0x76) [0x56894636] /builddir/ruby/ruby/vm_insnhelper.c:4772 
 /builddir/ruby/ruby/miniruby(vm_sendish+0xa2) [0x5689fecb] /builddir/ruby/ruby/vm_insnhelper.c:5961 
 /builddir/ruby/ruby/miniruby(vm_exec_core) /builddir/ruby/ruby/insns.def:898 
 /builddir/ruby/ruby/miniruby(vm_exec_loop+0x38) [0x56893d68] /builddir/ruby/ruby/vm.c:2622 
 /builddir/ruby/ruby/miniruby(rb_vm_exec) /builddir/ruby/ruby/vm.c:2598 
 /builddir/ruby/ruby/miniruby(rb_ec_exec_node+0x7f) [0x566eb0ef] /builddir/ruby/ruby/eval.c:281 
 /builddir/ruby/ruby/miniruby(ruby_run_node+0x58) [0x566ee558] /builddir/ruby/ruby/eval.c:319 
 /builddir/ruby/ruby/miniruby(main+0x70) [0x56648460] ./main.c:43 

 -- Other runtime information ----------------------------------------------- 

 * Loaded script: -e 

 * Loaded features: 

     0 enumerator.so 
     1 thread.rb 
     2 fiber.so 
     3 rational.so 
     4 complex.so 
     5 ruby2_keywords.rb 

 * Process memory map: 

 56622000-56642000 r--p 00000000 fe:02 9210459                              /builddir/ruby/ruby/miniruby 
 56642000-56941000 r-xp 00020000 fe:02 9210459                              /builddir/ruby/ruby/miniruby 
 56941000-56b4c000 r--p 0031f000 fe:02 9210459                              /builddir/ruby/ruby/miniruby 
 56b4c000-56b54000 r--p 0052a000 fe:02 9210459                              /builddir/ruby/ruby/miniruby 
 56b54000-56b55000 rw-p 00532000 fe:02 9210459                              /builddir/ruby/ruby/miniruby 
 56b55000-56b5e000 rw-p 00000000 00:00 0  
 58967000-58abb000 rw-p 00000000 00:00 0                                    [heap] 
 f43b8000-f5a48000 r--s 00000000 fe:02 9210459                              /builddir/ruby/ruby/miniruby 
 f5a48000-f5a4b000 r--p 00000000 fe:02 11307369                             /usr/lib/libgcc_s.so.1 
 f5a4b000-f5a79000 r-xp 00003000 fe:02 11307369                             /usr/lib/libgcc_s.so.1 
 f5a79000-f5a7e000 r--p 00031000 fe:02 11307369                             /usr/lib/libgcc_s.so.1 
 f5a7e000-f5a7f000 r--p 00035000 fe:02 11307369                             /usr/lib/libgcc_s.so.1 
 f5a7f000-f5a80000 rw-p 00036000 fe:02 11307369                             /usr/lib/libgcc_s.so.1 
 f5a80000-f5ab0000 rw-p 00000000 00:00 0                                    [anon:Ruby:GC:default:heap_page_body_allocate] 
 f5abf000-f5ac0000 ---p 00000000 00:00 0                                    [anon:Ruby:fiber_pool_allocate_memory] 
 f5ac0000-f5b11000 rw-p 00000000 00:00 0                                    [anon:Ruby:fiber_pool_allocate_memory] 
 f5b11000-f5b12000 ---p 00000000 00:00 0                                    [anon:Ruby:fiber_pool_allocate_memory] 
 f5b12000-f5b63000 rw-p 00000000 00:00 0                                    [anon:Ruby:fiber_pool_allocate_memory] 
 f5b63000-f5b64000 ---p 00000000 00:00 0                                    [anon:Ruby:fiber_pool_allocate_memory] 
 f5b64000-f5bb5000 rw-p 00000000 00:00 0                                    [anon:Ruby:fiber_pool_allocate_memory] 
 f5bb5000-f5bb6000 ---p 00000000 00:00 0                                    [anon:Ruby:fiber_pool_allocate_memory] 
 f5bb6000-f5c07000 rw-p 00000000 00:00 0                                    [anon:Ruby:fiber_pool_allocate_memory] 
 f5c07000-f5c08000 ---p 00000000 00:00 0                                    [anon:Ruby:fiber_pool_allocate_memory] 
 f5c08000-f5c59000 rw-p 00000000 00:00 0                                    [anon:Ruby:fiber_pool_allocate_memory] 
 f5c59000-f5c5a000 ---p 00000000 00:00 0                                    [anon:Ruby:fiber_pool_allocate_memory] 
 f5c5a000-f5cab000 rw-p 00000000 00:00 0                                    [anon:Ruby:fiber_pool_allocate_memory] 
 f5cab000-f5cac000 ---p 00000000 00:00 0                                    [anon:Ruby:fiber_pool_allocate_memory] 
 f5cac000-f5cfd000 rw-p 00000000 00:00 0                                    [anon:Ruby:fiber_pool_allocate_memory] 
 f5cfd000-f5cfe000 ---p 00000000 00:00 0                                    [anon:Ruby:fiber_pool_allocate_memory] 
 f5cfe000-f5d4f000 rw-p 00000000 00:00 0                                    [anon:Ruby:fiber_pool_allocate_memory] 
 f5d4f000-f5d50000 ---p 00000000 00:00 0  
 f5d50000-f6550000 rw-p 00000000 00:00 0  
 f6550000-f6590000 rw-p 00000000 00:00 0                                    [anon:Ruby:GC:default:heap_page_body_allocate] 
 f659f000-f759f000 rw-p 00000000 00:00 0                                    [anon:Ruby:Init_default_shapes:shape_cache] 
 f759f000-f765f000 rw-p 00000000 00:00 0                                    [anon:Ruby:Init_default_shapes:shape_list] 
 f765f000-f7690000 rw-p 00000000 00:00 0  
 f7690000-f76a0000 rw-p 00000000 00:00 0                                    [anon:Ruby:GC:default:heap_page_body_allocate] 
 f76a9000-f772a000 rw-p 00000000 00:00 0  
 f772a000-f79a4000 r--p 00074000 fe:02 11307480                             /usr/lib/locale/locale-archive 
 f79a4000-f7ba4000 r--p 00000000 fe:02 11307480                             /usr/lib/locale/locale-archive 
 f7ba4000-f7ba6000 rw-p 00000000 00:00 0  
 f7ba6000-f7bc9000 r--p 00000000 fe:02 11307064                             /usr/lib/libc.so.6 
 f7bc9000-f7d69000 r-xp 00023000 fe:02 11307064                             /usr/lib/libc.so.6 
 f7d69000-f7dc5000 r--p 001c3000 fe:02 11307064                             /usr/lib/libc.so.6 
 f7dc5000-f7dc7000 r--p 0021f000 fe:02 11307064                             /usr/lib/libc.so.6 
 f7dc7000-f7dc8000 rw-p 00221000 fe:02 11307064                             /usr/lib/libc.so.6 
 f7dc8000-f7dd2000 rw-p 00000000 00:00 0  
 f7dd2000-f7de0000 r--p 00000000 fe:02 11307059                             /usr/lib/libm.so.6 
 f7de0000-f7ead000 r-xp 0000e000 fe:02 11307059                             /usr/lib/libm.so.6 
 f7ead000-f7edf000 r--p 000db000 fe:02 11307059                             /usr/lib/libm.so.6 
 f7edf000-f7ee0000 r--p 0010c000 fe:02 11307059                             /usr/lib/libm.so.6 
 f7ee0000-f7ee1000 rw-p 0010d000 fe:02 11307059                             /usr/lib/libm.so.6 
 f7ee1000-f7ee2000 r--p 00000000 fe:02 11307767                             /usr/lib/libcrypt.so.2.0.0 
 f7ee2000-f7efe000 r-xp 00001000 fe:02 11307767                             /usr/lib/libcrypt.so.2.0.0 
 f7efe000-f7f18000 r--p 0001d000 fe:02 11307767                             /usr/lib/libcrypt.so.2.0.0 
 f7f18000-f7f19000 r--p 00036000 fe:02 11307767                             /usr/lib/libcrypt.so.2.0.0 
 f7f19000-f7f1a000 rw-p 00037000 fe:02 11307767                             /usr/lib/libcrypt.so.2.0.0 
 f7f1a000-f7f22000 rw-p 00000000 00:00 0  
 f7f22000-f7f24000 r--p 00000000 fe:02 11307365                             /usr/lib/libz.so.1.3.1 
 f7f24000-f7f34000 r-xp 00002000 fe:02 11307365                             /usr/lib/libz.so.1.3.1 
 f7f34000-f7f3a000 r--p 00012000 fe:02 11307365                             /usr/lib/libz.so.1.3.1 
 f7f3a000-f7f3b000 r--p 00017000 fe:02 11307365                             /usr/lib/libz.so.1.3.1 
 f7f3b000-f7f3c000 rw-p 00018000 fe:02 11307365                             /usr/lib/libz.so.1.3.1 
 f7f41000-f7f43000 rw-p 00000000 00:00 0  
 f7f43000-f7f45000 r--p 00000000 00:00 0                                    [vvar] 
 f7f45000-f7f47000 r--p 00000000 00:00 0                                    [vvar_vclock] 
 f7f47000-f7f49000 r-xp 00000000 00:00 0                                    [vdso] 
 f7f49000-f7f4a000 r--p 00000000 fe:02 11307070                             /usr/lib/ld-linux.so.2 
 f7f4a000-f7f72000 r-xp 00001000 fe:02 11307070                             /usr/lib/ld-linux.so.2 
 f7f72000-f7f7d000 r--p 00029000 fe:02 11307070                             /usr/lib/ld-linux.so.2 
 f7f7d000-f7f7f000 r--p 00034000 fe:02 11307070                             /usr/lib/ld-linux.so.2 
 f7f7f000-f7f80000 rw-p 00036000 fe:02 11307070                             /usr/lib/ld-linux.so.2 
 ff95d000-ff97e000 rw-p 00000000 00:00 0                                    [stack] 


 Segmentation fault 
 ``` 

 


 Backtrace in gdb: 

 ``` 
 Thread 1 "miniruby" received signal SIGSEGV, Segmentation fault. 
 search_nonascii (p=<optimized out>, e=0xb3b91049 <error: Cannot access memory at address 0xb3b91049>) at string.c:729 
 729                   if (*s & NONASCII_MASK) { 
 (gdb) bt 
 #0    search_nonascii (p=<optimized out>, e=0xb3b91049 <error: Cannot access memory at address 0xb3b91049>) at string.c:729 
 #1    0x56754d09 in coderange_scan (p=0xb3b91041 <error: Cannot access memory at address 0xb3b91041>, len=8, enc=0x56a961a0) 
     at string.c:767 
 #2    0x56757715 in enc_coderange_scan (str=4122077840, enc=<optimized out>) at ./include/ruby/internal/core/rstring.h:430 
 #3    rb_enc_str_coderange (str=4122077840) at string.c:910 
 #4    0x5675845c in str_succ (str=str@entry=4122077840) at string.c:5364 
 #5    0x5675cf85 in rb_str_succ_bang (str=4122077840) at string.c:5380 
 #6    0x567b90e6 in vm_call_cfunc_with_frame_ (ec=0x56a9598c, reg_cfp=0xf77a6fd8, calling=<optimized out>, argc=0, argv=0xf7727030,  
     stack_bottom=0xf772702c) at /builddir/ruby/ruby/vm_insnhelper.c:3794 
 #7    0x567c7636 in vm_call_method_each_type (ec=0x56a9598c, cfp=0xf77a6fd8, calling=0xffffd9e8) 
     at /builddir/ruby/ruby/vm_insnhelper.c:4772 
 #8    0x567d2ecb in vm_sendish (ec=<optimized out>, reg_cfp=<optimized out>, cd=<optimized out>, block_handler=<optimized out>,  
     method_explorer=<optimized out>) at /builddir/ruby/ruby/vm_callinfo.h:415 
 #9    vm_exec_core (ec=0xb3b91041, ec@entry=0x56a9598c) at /builddir/ruby/ruby/insns.def:898 
 #10 0x567c6d68 in vm_exec_loop (ec=<optimized out>, state=<optimized out>, tag=<optimized out>, result=10) at vm.c:2622 
 #11 rb_vm_exec (ec=0x56a9598c) at vm.c:2598 
 #12 0x5661e0ef in rb_ec_exec_node (ec=ec@entry=0x56a9598c, n=n@entry=0xf5b1eaf4) at eval.c:281 
 #13 0x56621558 in ruby_run_node (n=0xf5b1eaf4) at eval.c:319 
 #14 0x5657b460 in rb_main (argc=5, argv=0xffffdc34) at ./main.c:43 
 #15 main (argc=<optimized out>, argv=<optimized out>) at ./main.c:68 
 ``` 

 


 I can trigger this with "./configure CFLAGS="-O2 -g"    The -O2 is important.    With -flto=auto it goes away, with -O0 or -O3 too. 
 I use gcc (GCC) 14.2.1 20250405 on Void Linux with glibc 2.41.    On 64-bit x86_64 it works fine with same versions. 

 I have bisected the issue to https://github.com/ruby/ruby/commit/14d154076876 
 but I don't see how this can introduce the bug.    I assume it's some undefined behavior that is potentially triggered. 
 (However reverting that patch works...) 

 I think the behavior is related to the embedded string being expanded into a proper string, but my internal-fu isn't good enough. 

 I hope this helps to debug the issue.

Back