summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--bootstraptest/test_knownbug.rb5
-rw-r--r--eval_method.c8
-rw-r--r--thread.c9
4 files changed, 19 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index d47043d7a3..3f425cdb9c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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;
diff --git a/thread.c b/thread.c
index d199a39645..8fc6dd9245 100644
--- a/thread.c
+++ b/thread.c
@@ -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;
}