On Wed, Feb 22, 2006 at 02:21:24PM +0900, Eric Hodel wrote: > On Feb 5, 2006, at 5:05 AM, Mauricio Fernandez wrote: > >I'd conjecture that the above works on Linux because glibc's malloc() always > >returns 8-byte aligned memory addresses, which doesn't seem to be > >the case in > >OSX: > > > > 0x1d421c % 8 # => 4 > > OS X's malloc aligns memory on 16 byte boundaries. This problem is > not unique to OS X, you just need enough symbols. I was being stupid. I forgot that sizeof(RVALUE) % 8 = 4, so the alignment of the heap slots doesn't matter. > >Another possibility would be that the address space for the data > >segment > >used in OSX is lower than on Linux, so the SYM2ID matches an existent > >symbol: > > If you're close enough to the beginning of memory ObjectSpace#_id2ref > will pick a Symbol over the real object like you mention above: On my system the values returned by malloc start around 0xb7d00000 (when using brk) so I can hardly create enough symbols to force a collision, but I can get a crash on Linux with the following: batsman@tux-chan:~/mess/current$ cat symbols_overlap.rb Objs = (1..10000).map{ Object.new } STR = 'b!aaaaaaaa' def UNSIGNED(i) # too lazy to do it properly (0..(8*i.size-2)).map{|n| i[n]}.inject([0,1]){|(s,n),x| [s + x * 2**n,n+1]}.first end def ID2ULONG(i) i < 0 ? UNSIGNED(i) : i end $min = Symbol.all_symbols.sort_by{|s| s.object_id}.first def symbol_info min_id, max_id = [$min, $max].map{|s| ID2ULONG(s.object_id)} puts "last: #{$max.object_id} ===> #{Objs.object_id}" puts "extrema: id: 0x%010x ---- id: 0x%010x" % [min_id, max_id] puts " symbol: %10p ---- %10p" % [$min, $max] pending_before_crash = ((UNSIGNED(Objs.object_id) - max_id) / 2048) puts "About ~%d symbols expected before crash" % pending_before_crash pending_before_crash end def make_more_syms(num = 100000) $stdout.sync = true num.times do |n| print "\r%7d / %8d" % [n, num] if n % 10000 == 0 STR.intern $max = STR.intern STR.succ! end puts puts "Created #{num} new symbols" end puts "Objects around 0x%x " % ID2ULONG(Objs.object_id) make_more_syms(10001) pending = symbol_info (1..5).each do |i| make_more_syms((pending * 2**(-i)).to_i) symbol_info end batsman@tux-chan:~/mess/current$ ruby -v symbols_overlap.rb ruby 1.8.4 (2005-12-24) [i686-linux] Objects around 0xb7dbf2ec 10000 / 10001 Created 10001 new symbols last: 23144206 ===> -605161098 extrema: id: 0x000000210e ---- id: 0x000161270e symbol: :"!" ---- :"b!aaaaaouq" About ~1494873 symbols expected before crash 740000 / 747436 Created 747436 new symbols last: 1553893134 ===> -605161098 extrema: id: 0x000000210e ---- id: 0x005c9e870e symbol: :"!" ---- :"b!aaabrcme" About ~747437 symbols expected before crash 370000 / 373718 Created 373718 new symbols last: -1975699698 ===> -605161098 extrema: id: 0x000000210e ---- id: 0x00147a6e1c symbols_overlap.rb:18: [BUG] Segmentation fault ruby 1.8.4 (2005-12-24) [i686-linux] Aborted batsman@tux-chan:~/mess/current$ ruby19 -v symbols_overlap.rb ruby 1.9.0 (2006-01-14) [i686-linux] Objects around 0xb7dafea0 10000 / 10001 Created 10001 new symbols last: 23246606 ===> -605192368 extrema: id: 0x000000210e ---- id: 0x000162b70e symbol: :"!" ---- :"b!aaaaaouq" About ~1494792 symbols expected before crash 740000 / 747396 Created 747396 new symbols last: 1553913614 ===> -605192368 extrema: id: 0x000000210e ---- id: 0x005c9ed70e symbol: :"!" ---- :"b!aaabrckq" About ~747396 symbols expected before crash 370000 / 373698 Created 373698 new symbols last: -1975720178 ===> -605192368 extrema: id: 0x000000210e ---- id: 0x001479ce1c symbols_overlap.rb:18: [BUG] Segmentation fault ruby 1.9.0 (2006-01-14) [i686-linux] Aborted Some more info: (gdb) set args symbols_overlap.rb (gdb) run Starting program: /home/batsman/usr/bin/ruby19 symbols_overlap.rb Objects around 0xb7e11ea0 10000 / 10001 Created 10001 new symbols last: 23246606 ===> -604991664 extrema: id: 0x000000210e ---- id: 0x000162b70e symbol: :"!" ---- :"b!aaaaaouq" About ~1494988 symbols expected before crash 740000 / 747494 Created 747494 new symbols last: 1554114318 ===> -604991664 extrema: id: 0x000000210e ---- id: 0x005ca1e70e symbol: :"!" ---- :"b!aaabrcok" About ~747494 symbols expected before crash 370000 / 373747 Created 373747 new symbols last: -1975419122 ===> -604991664 extrema: id: 0x000000210e ---- id: 0x001482fe1c Program received signal SIGSEGV, Segmentation fault. 0x0808ccb4 in sym_inspect (sym=2319548174) at object.c:1053 1053 str = rb_str_new(0, strlen(name)+1); (gdb) p name $1 = 0x0 (gdb) where #0 0x0808ccb4 in sym_inspect (sym=2319548174) at object.c:1053 #1 0x08060d0b in call_cfunc (func=0x808cc82 <sym_inspect>, recv=2319548174, len=0, argc=0, argv=0x0) at eval.c:5435 #2 0x080605b2 in rb_call0 (klass=3085058588, recv=2319548174, id=3185, oid=3185, argc=0, argv=0x0, body=0xb7e2417c, flags=8) at eval.c:5643 #3 0x0806162d in rb_call (klass=3085058588, recv=2319548174, mid=3185, argc=0, argv=0x0, scope=CALLING_FCALL) at eval.c:5816 #4 0x08061835 in rb_funcall (recv=2319548174, mid=3185, n=0) at eval.c:5916 #5 0x0808c439 in rb_inspect (obj=2319548174) at object.c:301 #6 0x080d0754 in rb_str_format (argc=3, argv=0xc6804fc, fmt=3084987368) at sprintf.c:414 #7 0x080d498a in rb_str_format_m (str=3084545100, arg=3084539600) at string.c:413 #8 0x08060d2a in call_cfunc (func=0x80d495a <rb_str_format_m>, recv=3084545100, len=1, argc=1, argv=0xbfadf730) at eval.c:5438 #9 0x080605b2 in rb_call0 (klass=3085051628, recv=3084545100, id=37, oid=37, argc=1, argv=0xbfadf730, body=0xb7e2250c, flags=0) at eval.c:5643 #10 0x0806162d in rb_call (klass=3085051628, recv=3084545100, mid=37, argc=1, argv=0xbfadf730, scope=CALLING_NORMAL) at eval.c:5816 #11 0x0805aba6 in rb_eval (self=3085056528, n=0xb7e12b70) at eval.c:3278 #12 0x0805ad0d in rb_eval (self=3085056528, n=0xb7e12d28) at eval.c:3288 #13 0x080609d9 in rb_call0 (klass=3085061408, recv=3085056528, id=10737, oid=10737, argc=0, argv=0x0, body=0xb7e12d28, flags=10) at eval.c:5724 #14 0x0806162d in rb_call (klass=3085061408, recv=3085056528, mid=10737, argc=0, argv=0x0, scope=CALLING_VCALL) at eval.c:5816 #15 0x0805ae8e in rb_eval (self=3085056528, n=0xb7e11f04) at eval.c:3299 #16 0x0805e86a in rb_yield_0 (val=5, self=3085056528, klass=0, flags=0, avalue=0) at eval.c:4821 #17 0x0805ec02 in rb_yield (val=5) at eval.c:4902 #18 0x080aaf91 in range_each (range=3084984468) at range.c:389 #19 0x08060d0b in call_cfunc (func=0x80aae93 <range_each>, recv=3084984468, len=0, argc=0, argv=0x0) at eval.c:5435 #20 0x080605b2 in rb_call0 (klass=3085021928, recv=3084984468, id=3905, oid=3905, argc=0, argv=0x0, body=0xb7e1b1e4, flags=0) at eval.c:5643 #21 0x0806162d in rb_call (klass=3085021928, recv=3084984468, mid=3905, argc=0, argv=0x0, scope=CALLING_NORMAL) at eval.c:5816 #22 0x0805aba6 in rb_eval (self=3085056528, n=0xb7e12080) at eval.c:3278 #23 0x08059982 in rb_eval (self=3085056528, n=0xb7e138e0) at eval.c:3002 #24 0x08055f58 in eval_node (self=3085056528, node=0xb7e138e0) at eval.c:1337 #25 0x0805655e in ruby_exec_internal () at eval.c:1515 #26 0x080565ac in ruby_exec () at eval.c:1531 #27 0x080565e9 in ruby_run () at eval.c:1547 #28 0x080543ce in main (argc=2, argv=0xbfae1684, envp=0xbfae1690) at main.c:43 (gdb) list object.c:1053 1048 VALUE str; 1049 char *name; 1050 ID id = SYM2ID(sym); 1051 1052 name = rb_id2name(id); 1053 str = rb_str_new(0, strlen(name)+1); 1054 RSTRING(str)->ptr[0] = ':'; 1055 strcpy(RSTRING(str)->ptr+1, name); 1056 if (!rb_symname_p(name)) { 1057 str = rb_str_dump(str); -- Mauricio Fernandez - http://eigenclass.org - non-trivial Ruby