diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | bootstraptest/test_knownbug.rb | 5 | ||||
-rw-r--r-- | eval_method.c | 8 | ||||
-rw-r--r-- | thread.c | 9 |
4 files changed, 19 insertions, 11 deletions
@@ -1,3 +1,11 @@ +Sat Mar 1 12:15:42 2008 Yukihiro Matsumoto <matz@ruby-lang.org> + + * eval_method.c (rb_get_method_body): ent->method may be freed by + GC. [ruby-dev:31819] + + * thread.c (remove_event_hook): should not access freed memory. + [ruby-dev:31820] + Sat Mar 01 10:31:19 2008 NARUSE, Yui <naruse@ruby-lang.org> * io.c (read_all, rb_io_getline_fast): encoding is io_input_encoding. diff --git a/bootstraptest/test_knownbug.rb b/bootstraptest/test_knownbug.rb index 6aedfbb6e5..c23aade793 100644 --- a/bootstraptest/test_knownbug.rb +++ b/bootstraptest/test_knownbug.rb @@ -29,11 +29,6 @@ assert_equal 'ok', %q{ C.new.foo }, '[ruby-core:14813]' -# test is not written... -flunk '[ruby-dev:31819] rb_clear_cache_by_class' -flunk '[ruby-dev:31820] valgrind set_trace_func' -flunk '[ruby-dev:32746] Invalid read of size 1' - assert_equal 'ok', %q{ class X < RuntimeError;end x = [X] diff --git a/eval_method.c b/eval_method.c index f7043c0069..7ff683d219 100644 --- a/eval_method.c +++ b/eval_method.c @@ -11,6 +11,7 @@ struct cache_entry { /* method hash table. */ ID mid; /* method's id */ ID mid0; /* method's original id */ VALUE klass; /* receiver's class */ + VALUE oklass; /* original's class */ NODE *method; }; @@ -46,7 +47,7 @@ rb_clear_cache_for_undef(VALUE klass, ID id) ent = cache; end = ent + CACHE_SIZE; while (ent < end) { - if (ent->method && ent->method->nd_clss == klass && ent->mid == id) { + if (ent->oklass == klass && ent->mid == id) { ent->mid = 0; } ent++; @@ -84,8 +85,7 @@ rb_clear_cache_by_class(VALUE klass) ent = cache; end = ent + CACHE_SIZE; while (ent < end) { - if ((ent->klass == klass) || - (ent->method && ent->method->nd_clss == klass)) { + if (ent->klass == klass || ent->oklass == klass) { ent->mid = 0; } ent++; @@ -250,6 +250,7 @@ rb_get_method_body(VALUE klass, ID id, ID *idp) ent->klass = klass; ent->mid = ent->mid0 = id; ent->method = 0; + ent->oklass = 0; return 0; } @@ -263,6 +264,7 @@ rb_get_method_body(VALUE klass, ID id, ID *idp) ent->mid = id; ent->mid0 = fbody->nd_oid; ent->method = body = method; + ent->oklass = method->nd_clss; } else { body = method; @@ -2757,9 +2757,10 @@ rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data) static int remove_event_hook(rb_event_hook_t **root, rb_event_hook_func_t func) { - rb_event_hook_t *prev = NULL, *hook = *root; + rb_event_hook_t *prev = NULL, *hook = *root, *next; while (hook) { + next = hook->next; if (func == 0 || hook->func == func) { if (prev) { prev->next = hook->next; @@ -2769,8 +2770,10 @@ remove_event_hook(rb_event_hook_t **root, rb_event_hook_func_t func) } xfree(hook); } - prev = hook; - hook = hook->next; + else { + prev = hook; + } + hook = next; } return -1; } |