[ruby-trunk - Bug #10646] [Closed] wmap_final_func の xrealloc で確保するメモリのサイズが1足りないためSEGV


Issue #10646 has been updated by Naohisa G…

Status changed from Open to Closed
% Done changed from 0 to 100

Applied in changeset r48999.

  • gc.c (wmap_final_func): fix memory size shortage when realloc wmap.
    Fix SEGV during finilize of WeakRef on Solaris (though the SEGV
    could occur on all OS/platforms). [ruby-dev:48779] [Bug #10646]

Bug #10646: wmap_final_func の xrealloc で確保するメモリのサイズが1足りないためSEGV

  • Author: Naohisa G.
  • Status: Closed
  • Priority: Normal
  • Assignee:
  • Category:
  • Target version:
  • ruby -v: ruby 2.2.0dev (2014-12-25) [sparc64-solaris2.10]
  • Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN

(r48972 にて確認)

$ LD_PRELOAD=libumem.so UMEM_OPTIONS="backend=mmap" /usr/bin/time 
/XXXXX/bin/ruby -r weakref -e 'a = Object.new; 150_000.times { 
WeakRef.new(a) }'
/XXXXX/lib/ruby/2.2.0/weakref.rb:87: [BUG] Segmentation fault at 
ruby 2.2.0dev (2014-12-24) [sparc64-solaris2.10]

-- Control frame information 
c:0008 p:---- s:0022 e:000021 CFUNC  :finalize
c:0007 p:---- s:0020 e:000019 CFUNC  :call
c:0006 p:0039 s:0018 e:000017 METHOD /XXXXX/lib/ruby/2.2.0/weakref.rb:87 
c:0005 p:---- s:0014 e:000013 CFUNC  :new
c:0004 p:0015 s:0010 e:000009 BLOCK  -e:1 [FINISH]
c:0003 p:---- s:0008 e:000007 CFUNC  :times
c:0002 p:0017 s:0005 E:001398 EVAL   -e:1 [FINISH]
c:0001 p:0000 s:0002 E:000e50 TOP    [FINISH]

-- Ruby level backtrace information 
-e:1:in `<main>'
-e:1:in `times'
-e:1:in `block in <main>'
-e:1:in `new'
/XXXXX/lib/ruby/2.2.0/weakref.rb:87:in `initialize'
/XXXXX/lib/ruby/2.2.0/weakref.rb:87:in `call'
/XXXXX/lib/ruby/2.2.0/weakref.rb:87:in `finalize'

-- Other runtime information 

* Loaded script: -e

* Loaded features:

    0 enumerator.so
    1 rational.so
    2 complex.so
    3 /XXXXX/lib/ruby/2.2.0/sparc64-solaris2.10/enc/encdb.so
    4 /XXXXX/lib/ruby/2.2.0/sparc64-solaris2.10/enc/trans/transdb.so
    5 /XXXXX/lib/ruby/2.2.0/unicode_normalize.rb
    6 /XXXXX/lib/ruby/2.2.0/sparc64-solaris2.10/rbconfig.rb
    7 thread.rb
    8 /XXXXX/lib/ruby/2.2.0/sparc64-solaris2.10/thread.so
    9 /XXXXX/lib/ruby/2.2.0/rubygems/compatibility.rb
   10 /XXXXX/lib/ruby/2.2.0/rubygems/defaults.rb
   11 /XXXXX/lib/ruby/2.2.0/rubygems/deprecate.rb
   12 /XXXXX/lib/ruby/2.2.0/rubygems/errors.rb
   13 /XXXXX/lib/ruby/2.2.0/rubygems/version.rb
   14 /XXXXX/lib/ruby/2.2.0/rubygems/requirement.rb
   15 /XXXXX/lib/ruby/2.2.0/rubygems/platform.rb
   16 /XXXXX/lib/ruby/2.2.0/rubygems/basic_specification.rb
   17 /XXXXX/lib/ruby/2.2.0/rubygems/stub_specification.rb
   18 /XXXXX/lib/ruby/2.2.0/rubygems/util/stringio.rb
   19 /XXXXX/lib/ruby/2.2.0/rubygems/specification.rb
   20 /XXXXX/lib/ruby/2.2.0/rubygems/exceptions.rb
   21 /XXXXX/lib/ruby/2.2.0/rubygems/core_ext/kernel_gem.rb
   22 /XXXXX/lib/ruby/2.2.0/monitor.rb
   23 /XXXXX/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb
   24 /XXXXX/lib/ruby/2.2.0/rubygems.rb
   25 /XXXXX/lib/ruby/2.2.0/delegate.rb
   26 /XXXXX/lib/ruby/2.2.0/weakref.rb

You may have encountered a bug in the Ruby interpreter or extension 
Bug reports are welcome.
For details: http://www.ruby-lang.org/bugreport.html

time: command terminated abnormally.

real       33.2
user       21.3
sys        11.5


$ dbx /XXXXX/bin/ruby
For information about new features see `help changes'
To remove this message, put `dbxenv suppress_startup_message 7.5' in 
your .dbxrc
Reading ruby
Reading ld.so.1
Reading libumem.so.1
Reading libpthread.so.1
Reading librt.so.1
Reading libgmp.so.10.1.3
Reading libsocket.so.1
Reading libdl.so.1
Reading libcrypt_d.so.1
Reading libm.so.2
Reading libc.so.1
Reading libaio.so.1
Reading libmd.so.1
Reading libnsl.so.1
Reading libgen.so.1
(dbx) run -r  weakref -e 'a = Object.new; 150_000.times { WeakRef.new(a) 
Running: ruby -r weakref -e "a = Object.new; 150_000.times { 
WeakRef.new(a) }"
(process id 6241)
Reading libc_psr.so.1
Reading encdb.so
Reading transdb.so
Reading thread.so
t@1 (l@1) signal SEGV (access to address exceeded protections) in 
wmap_final_func at line 7666 in file "gc.c"
 7666           if (ptr[i] != wmap) {
(dbx) print i
i = 103422U
(dbx) print j
j = 103421U
(dbx) print wmap
wmap = 9223372034650698920U
(dbx) print ptr
ptr = 0x7fffffff77200010
(dbx) print ptr[0]
ptr[0] = 103422U
(dbx) print ptr[i]
dbx: cannot access address 0x7fffffff772ca000
(dbx) print ptr[j]
ptr[j] = 9223372034650719480U
(dbx) print ptr[103422]
dbx: cannot access address 0x7fffffff772ca000
(dbx) print ptr[103421]
ptr[103421] = 9223372034650719480U

このため、ptr[0]の数+1のメモリを確保する必要がありますが、wmap_final_func() 内の
ruby_sized_xrealloc2() での確保時に +1 が忘れ去られていました。


Index: gc.c
--- gc.c  (revision 48988)
+++ gc.c  (working copy)
@@ -7672,7 +7672,7 @@
   return ST_DELETE;
     if (j < i) {
-  ptr = ruby_sized_xrealloc2(ptr, j, sizeof(VALUE), i);
+  ptr = ruby_sized_xrealloc2(ptr, j + 1, sizeof(VALUE), i);
   ptr[0] = j;
   *value = (st_data_t)ptr;