summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--compar.c9
-rw-r--r--include/ruby/intern.h1
-rw-r--r--test/ruby/test_comparable.rb7
-rw-r--r--thread.c12
-rw-r--r--version.h2
6 files changed, 36 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index c8d28b719f..cb9e93121c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Thu Oct 10 01:14:37 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * compar.c (cmp_eq): fail if recursion. [ruby-core:57736] [Bug #9003]
+
+ * thread.c (rb_exec_recursive_paired_outer): new function which is
+ combinnation of paired and outer variants.
+
Thu Oct 10 01:07:37 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
* lib/tempfile.rb (Tempfile#unlink): finalizer is no longer needed
diff --git a/compar.c b/compar.c
index c89c752daf..fc04946e3f 100644
--- a/compar.c
+++ b/compar.c
@@ -52,9 +52,16 @@ rb_invcmp(VALUE x, VALUE y)
}
static VALUE
+cmp_eq_recursive(VALUE arg1, VALUE arg2, int recursive)
+{
+ if (recursive) return Qfalse;
+ return rb_funcall(arg1, cmp, 1, arg2);
+}
+
+static VALUE
cmp_eq(VALUE *a)
{
- VALUE c = rb_funcall(a[0], cmp, 1, a[1]);
+ VALUE c = rb_exec_recursive_paired_outer(cmp_eq_recursive, a[0], a[1], a[1]);
if (NIL_P(c)) return Qfalse;
if (rb_cmpint(c, a[0], a[1]) == 0) return Qtrue;
diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index c447b37223..b1dff0b7b9 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -426,6 +426,7 @@ void rb_thread_atfork_before_exec(void);
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE);
VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE,VALUE);
VALUE rb_exec_recursive_outer(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE);
+VALUE rb_exec_recursive_paired_outer(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE,VALUE);
/* dir.c */
VALUE rb_dir_getwd(void);
/* file.c */
diff --git a/test/ruby/test_comparable.rb b/test/ruby/test_comparable.rb
index c686adeceb..747f1e29a7 100644
--- a/test/ruby/test_comparable.rb
+++ b/test/ruby/test_comparable.rb
@@ -76,4 +76,11 @@ class TestComparable < Test::Unit::TestCase
assert_nil(Time.new <=> "")
}
end
+
+ def test_no_cmp
+ bug9003 = '[ruby-core:57736] [Bug #9003]'
+ assert_nothing_raised(SystemStackError, bug9003) {
+ @o <=> @o.dup
+ }
+ end
end
diff --git a/thread.c b/thread.c
index b2ec68a623..d859982fe5 100644
--- a/thread.c
+++ b/thread.c
@@ -4878,6 +4878,18 @@ rb_exec_recursive_outer(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg)
}
/*
+ * If recursion is detected on the current method, obj and paired_obj,
+ * the outermost func will be called with (obj, arg, Qtrue). All inner
+ * func will be short-circuited using throw.
+ */
+
+VALUE
+rb_exec_recursive_paired_outer(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE paired_obj, VALUE arg)
+{
+ return exec_recursive(func, obj, rb_obj_id(paired_obj), arg, 1);
+}
+
+/*
* call-seq:
* thr.backtrace -> array
*
diff --git a/version.h b/version.h
index f4b1ecfc7f..8ac1ebe8ad 100644
--- a/version.h
+++ b/version.h
@@ -1,6 +1,6 @@
#define RUBY_VERSION "2.0.0"
#define RUBY_RELEASE_DATE "2013-10-10"
-#define RUBY_PATCHLEVEL 333
+#define RUBY_PATCHLEVEL 334
#define RUBY_RELEASE_YEAR 2013
#define RUBY_RELEASE_MONTH 10