summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--enum.c6
-rw-r--r--eval.c32
-rw-r--r--vm_eval.c42
4 files changed, 56 insertions, 34 deletions
diff --git a/ChangeLog b/ChangeLog
index f46ff226ed..750df19841 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Fri Oct 30 02:11:36 2009 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * enum.c (enum_count): call #size using rb_funcall_no_recursive()
+ to prevent infinite recursive calls. [ruby-core:24794]
+
+ * vm_eval.c (rb_funcall_no_recursive): utility function to check
+ direct recursive call.
+
+ * vm_eval.c (rb_check_funcall): move from eval.c. [refactoring]
+
Thu Oct 29 18:37:02 2009 NARUSE, Yui <naruse@ruby-lang.org>
* encoding.c (Init_Encoding): revert previous commit.
diff --git a/enum.c b/enum.c
index c1efb1b5c2..aa3a9b7af3 100644
--- a/enum.c
+++ b/enum.c
@@ -119,6 +119,8 @@ count_all_i(VALUE i, VALUE memop, int argc, VALUE *argv)
return Qnil;
}
+extern VALUE rb_funcall_no_recursive(VALUE, ID, int, VALUE*, VALUE (*)());
+
/*
* call-seq:
* enum.count => int
@@ -150,8 +152,8 @@ enum_count(int argc, VALUE *argv, VALUE obj)
}
else {
VALUE tmp;
-
- tmp = rb_check_funcall(obj, id_size, 0, 0);
+
+ tmp = rb_funcall_no_recursive(obj, id_size, 0, 0, enum_count);
if (tmp != Qundef) return tmp;
func = count_all_i;
}
diff --git a/eval.c b/eval.c
index dec628204a..8fc06da910 100644
--- a/eval.c
+++ b/eval.c
@@ -492,38 +492,6 @@ rb_f_raise(int argc, VALUE *argv)
return Qnil; /* not reached */
}
-struct rescue_funcall_args {
- VALUE obj;
- ID id;
- int argc;
- VALUE *argv;
-};
-
-static VALUE
-check_funcall(struct rescue_funcall_args *args)
-{
- return rb_funcall2(args->obj, args->id, args->argc, args->argv);
-}
-
-static VALUE
-check_failed(VALUE data)
-{
- return data;
-}
-
-VALUE
-rb_check_funcall(VALUE obj, ID id, int argc, VALUE *argv)
-{
- struct rescue_funcall_args args;
-
- args.obj = obj;
- args.id = id;
- args.argc = argc;
- args.argv = argv;
- return rb_rescue2(check_funcall, (VALUE)&args, check_failed, Qundef,
- rb_eNoMethodError, (VALUE)0);
-}
-
static VALUE
make_exception(int argc, VALUE *argv, int isstr)
{
diff --git a/vm_eval.c b/vm_eval.c
index 8fbe82d102..309f997a1f 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -536,6 +536,48 @@ rb_funcall3(VALUE recv, ID mid, int argc, const VALUE *argv)
return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
}
+struct rescue_funcall_args {
+ VALUE obj;
+ ID id;
+ int argc;
+ VALUE *argv;
+};
+
+static VALUE
+check_funcall(struct rescue_funcall_args *args)
+{
+ return rb_funcall2(args->obj, args->id, args->argc, args->argv);
+}
+
+static VALUE
+check_failed(VALUE data)
+{
+ return data;
+}
+
+VALUE
+rb_check_funcall(VALUE obj, ID id, int argc, VALUE *argv)
+{
+ struct rescue_funcall_args args;
+
+ args.obj = obj;
+ args.id = id;
+ args.argc = argc;
+ args.argv = argv;
+ return rb_rescue2(check_funcall, (VALUE)&args, check_failed, Qundef,
+ rb_eNoMethodError, (VALUE)0);
+}
+
+VALUE
+rb_funcall_no_recursive(VALUE obj, ID id, int argc, VALUE *argv, VALUE (*func)())
+{
+ const rb_method_entry_t *me = rb_method_entry(CLASS_OF(obj), id);
+ if (me && me->def && me->def->type == VM_METHOD_TYPE_CFUNC &&
+ me->def->body.cfunc.func == func)
+ return Qundef;
+ return rb_check_funcall(obj, id, argc, argv);
+}
+
static VALUE
send_internal(int argc, const VALUE *argv, VALUE recv, int scope)
{