From: ngotogenome@... Date: 2014-12-25T08:33:53+00:00 Subject: [ruby-dev:48780] [ruby-trunk - Bug #10646] [Closed] wmap_final_func の xrealloc で確保するメモリのサイズが1足りないためSEGV Issue #10646 has been updated by Naohisa Goto. 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 https://bugs.ruby-lang.org/issues/10646#change-50629 * Author: Naohisa Goto * 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 ---------------------------------------- Solaris にて、以下のようにメモリリークを発見するデバッグ用のmallocを使用すると、WeakRefのfinalize中にSEGVが発生します。 (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 0x7fffffff7806a000 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 [FINISH] 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 `
' -e:1:in `times' -e:1:in `block in
' -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 [NOTE] You may have encountered a bug in the Ruby interpreter or extension libraries. 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]がその配列ptrの要素数を格納する場所ですが、この数字はptr[0]の場所を考慮しない要素数、つまりptr[1]からptr[ptr[0]]までアクセスされる可能性があります。 このため、ptr[0]の数+1のメモリを確保する必要がありますが、wmap_final_func() 内の ruby_sized_xrealloc2() での確保時に +1 が忘れ去られていました。 以下のパッチでSEGVは出なくなりました。 ~~~ 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; } ~~~ 今回、たまたまSolarisにて露見しましたが、本来はOSやCPUとは無関係のバグです。 -- https://bugs.ruby-lang.org/