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
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 `<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
[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とは無関係のバグです。