[bug:trunk] Invalid read of size 4 by redefining load

e$B0J2<$N$h$&$Ke(B load e$BCf$Ke(B load
e$B$r:FDj5A$9$k$H!“JQ$J$H$3$m$r%”%/%;%9$9$k$N$,e(B
valgrind e$B$G4QB,$5$l$^$9!#e(B

% cat tst.rb
module Kernel
def load(*args)
end
end
raise
% valgrind ./ruby -ve ‘load “tst.rb”’
==12820== Memcheck, a memory error detector.
==12820== Copyright © 2002-2007, and GNU GPL’d, by Julian Seward et
al.
==12820== Using LibVEX rev 1854, a library for dynamic binary
translation.
==12820== Copyright © 2004-2007, and GNU GPL’d, by OpenWorks LLP.
==12820== Using valgrind-3.3.1-Debian, a dynamic binary
instrumentation framework.
==12820== Copyright © 2000-2007, and GNU GPL’d, by Julian Seward et
al.
==12820== For more details, rerun with: -v
==12820==
ruby 1.9.2dev (2010-02-21 trunk 26723) [i686-linux]
tst.rb:2: warning: method redefined; discarding old load
==12820== Invalid read of size 4
==12820== at 0x814EA8F: vm_backtrace_each (vm.c:737)
==12820== by 0x814EBF2: vm_backtrace (vm.c:771)
==12820== by 0x814D1EE: rb_make_backtrace (vm_eval.c:1590)
==12820== by 0x805EB30: setup_exception (eval.c:378)
==12820== by 0x805F142: rb_raise_jump (eval.c:573)
==12820== by 0x805EF34: rb_f_raise (eval.c:503)
==12820== by 0x8147821: call_cfunc (vm_insnhelper.c:290)
==12820== by 0x81476F9: vm_call_cfunc (vm_insnhelper.c:377)
==12820== by 0x8146CC2: vm_call_method (vm_insnhelper.c:500)
==12820== by 0x81428F8: vm_exec_core (insns.def:999)
==12820== by 0x814F7C5: vm_exec (vm.c:1132)
==12820== by 0x814FF65: rb_iseq_eval (vm.c:1359)
==12820== Address 0x434c014 is 4 bytes inside a block of size 16 free’d
==12820== at 0x4022B8A: free (vg_replace_malloc.c:323)
==12820== by 0x8063B6E: vm_xfree (gc.c:731)
==12820== by 0x8063CC5: ruby_xfree (gc.c:779)
==12820== by 0x814848B: rb_free_method_entry (vm_method.c:141)
==12820== by 0x814881B: rb_add_method_def (vm_method.c:213)
==12820== by 0x81489EC: rb_add_method (vm_method.c:263)
==12820== by 0x8150D8E: vm_define_method (vm.c:1846)
==12820== by 0x8150E3E: m_core_define_method (vm.c:1862)
==12820== by 0x81478B8: call_cfunc (vm_insnhelper.c:302)
==12820== by 0x81476F9: vm_call_cfunc (vm_insnhelper.c:377)
==12820== by 0x8146CC2: vm_call_method (vm_insnhelper.c:500)
==12820== by 0x81428F8: vm_exec_core (insns.def:999)
==12820==
==12820== Invalid read of size 4
==12820== at 0x814EAAD: vm_backtrace_each (vm.c:740)
==12820== by 0x814EBF2: vm_backtrace (vm.c:771)
==12820== by 0x814D1EE: rb_make_backtrace (vm_eval.c:1590)
==12820== by 0x805EB30: setup_exception (eval.c:378)
==12820== by 0x805F142: rb_raise_jump (eval.c:573)
==12820== by 0x805EF34: rb_f_raise (eval.c:503)
==12820== by 0x8147821: call_cfunc (vm_insnhelper.c:290)
==12820== by 0x81476F9: vm_call_cfunc (vm_insnhelper.c:377)
==12820== by 0x8146CC2: vm_call_method (vm_insnhelper.c:500)
==12820== by 0x81428F8: vm_exec_core (insns.def:999)
==12820== by 0x814F7C5: vm_exec (vm.c:1132)
==12820== by 0x814FF65: rb_iseq_eval (vm.c:1359)
==12820== Address 0x434c018 is 8 bytes inside a block of size 16 free’d
==12820== at 0x4022B8A: free (vg_replace_malloc.c:323)
==12820== by 0x8063B6E: vm_xfree (gc.c:731)
==12820== by 0x8063CC5: ruby_xfree (gc.c:779)
==12820== by 0x814848B: rb_free_method_entry (vm_method.c:141)
==12820== by 0x814881B: rb_add_method_def (vm_method.c:213)
==12820== by 0x81489EC: rb_add_method (vm_method.c:263)
==12820== by 0x8150D8E: vm_define_method (vm.c:1846)
==12820== by 0x8150E3E: m_core_define_method (vm.c:1862)
==12820== by 0x81478B8: call_cfunc (vm_insnhelper.c:302)
==12820== by 0x81476F9: vm_call_cfunc (vm_insnhelper.c:377)
==12820== by 0x8146CC2: vm_call_method (vm_insnhelper.c:500)
==12820== by 0x81428F8: vm_exec_core (insns.def:999)
tst.rb:5:in <top (required)>': unhandled exception from -e:1:inload’
from -e:1:in `’
==12820==
==12820== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 29 from
1)
==12820== malloc/free: in use at exit: 615,707 bytes in 14,666 blocks.
==12820== malloc/free: 16,023 allocs, 1,357 frees, 1,662,183 bytes
allocated.
==12820== For counts of detected errors, rerun with: -v
==12820== searching for pointers to 14,666 not-freed blocks.
==12820== checked 451,824 bytes.
==12820==
==12820== LEAK SUMMARY:
==12820== definitely lost: 467,917 bytes in 9,809 blocks.
==12820== possibly lost: 0 bytes in 0 blocks.
==12820== still reachable: 147,790 bytes in 4,857 blocks.
==12820== suppressed: 0 bytes in 0 blocks.
==12820== Rerun with --leak-check=full to see details of leaked memory.

e$B$J$+$@$G$9!#e(B

At Mon, 22 Feb 2010 01:20:07 +0900,
Tanaka A. wrote in [ruby-dev:40452]:

e$B0J2<$N$h$&$Ke(B load e$BCf$Ke(B load e$B$r:FDj5A$9$k$H!“JQ$J$H$3$m$r%”%/%;%9$9$k$N$,e(B
valgrind e$B$G4QB,$5$l$^$9!#e(B

rb_method_entry_te$B$K$be(Brefcounte$B$rF~$l$^$9$+$M$’!#e(B

(2010/02/22 15:03), Nobuyoshi N. wrote::

rb_method_entry_te$B$K$be(Brefcounte$B$rF~$l$^$9$+$M$’!#e(B

e$B!!@-G=$N4QE@$+$iH?BP$7$^$9!%e(B

e$B!!$5$C$-$Ne(B IRC
e$B$K=q$$$?FbMF$G$9$,!$$3$s$J46$8$G$I$&$G$7$g$&$+!%Bg6D$J5$e(B
e$B$b$7$^$9$,!%e(B

(1) unlink e$B$5$l$?e(B me e$B$rJ]B8$7$F$*$/e(B
(2)
e$B0lDj$N%?%$%%s%0!JB?J,!$e(BGCe$B%?%$%%s%0!K$G%U%l!<%`$rAv::$7$Fe(B
e$B!!!J]B8$7$?e(B me e$B$Ke(B mark
(3) mark e$B$,$D$$$F$J$$$N$r>C$9!Je(Bsweepe$B!Ke(B

e$B!!e(BNODE e$B$KLa$9$C$F$N$b0l0F$G$9$,e(B…e$B!%e(B

e$B%A%1%C%He(B #2777 e$B$,99?7$5$l$^$7$?!#e(B (by Koichi Sasada)

e$B%9%F!<%?%9e(B Opene$B$+$ie(BClosede$B$KJQ99e(B
e$B?JD=e(B % 0e$B$+$ie(B100e$B$KJQ99e(B

This issue was solved with changeset r27634.
Nobuyoshi, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


http://redmine.ruby-lang.org/issues/show/2777

e$B%A%1%C%He(B #2777 e$B$,99?7$5$l$^$7$?!#e(B (by Yusuke E.)

e$BC4Ev<Te(B Koichi Sasadae$B$K%;%C%He(B
e$BM%@hEYe(B Lowe$B$+$ie(BNormale$B$KJQ99e(B
Target version 1.9.2e$B$K%;%C%He(B
ruby -v -e$B$K%;%C%He(B

e$B1sF#$G$9!#e(B

% cat tst.rb
module Kernel
def load(*args)
end
end
raise
% valgrind ./ruby -ve ‘load “tst.rb”’
snip

e$B$H$$$&%%j%8%J%k$NLdBj$Oe(B r27393
e$B$G9
L/$K2sHr$5$l$^$7$?$,!"K<AE*$K$Oe(B
e$B2r7h$7$F$*$i$:!"0J2<$Ge(B SEGV e$B$7$^$9!#e(B

class C
define_method(:foo) do
C.class_eval { remove_method(:foo) }
super()
end
end
C.new.foo

e$B$"$H!"e(Br27393 e$B$@$He(B rb_method_definition_t
e$B$N;2>H$r8:$i$7$F$$$J$$$N$Ge(B
e$B%a%b%j%j!<%/$9$k$h$&$J5$$,$7$^$9!#e(B

diff --git a/vm_method.c b/vm_method.c
index 04b62f2…c9d99db 100644
— a/vm_method.c
+++ b/vm_method.c
@@ -215,6 +215,14 @@ rb_add_method_def(VALUE klass, ID mid,
rb_method_type_t type, rb_method_definiti
* another problem when the usage is changed.
*/
me = old_me;
+

  • if (me->def) {
  •  if (me->def->alias_count == 0)
    
  • xfree(me->def);
  •  else if (me->def->alias_count > 0)
    
  • me->def->alias_count–;
  •  me->def = 0;
    
  • }
    }
    else {
    me = ALLOC(rb_method_entry_t);


Yusuke E. [email protected]

http://redmine.ruby-lang.org/issues/show/2777