summaryrefslogtreecommitdiff
path: root/array.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-02-26 06:30:38 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-02-26 06:30:38 +0000
commiteccb4ca2e71611ecca616f8c57bc087898a17c91 (patch)
treeb262b0e98686465b06d521e1115f5c944081a4d6 /array.c
parentc4693e62afaa5547be208b60b8b7fe79acc58aa5 (diff)
* array.c (rb_ary_eql, rb_ary_cmp): get rid of stack overflow with
self-recursive constructs. [ruby-Bugs-18356] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@15607 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'array.c')
-rw-r--r--array.c58
1 files changed, 39 insertions, 19 deletions
diff --git a/array.c b/array.c
index 1f1526354d..b92d3fb5d3 100644
--- a/array.c
+++ b/array.c
@@ -317,7 +317,7 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
rb_raise(rb_eArgError, "array size too big");
}
rb_ary_modify(ary);
- RESIZE_CAPA(ary, len);
+ RESIZE_CAPA(ary, len);
if (rb_block_given_p()) {
long i;
@@ -2343,6 +2343,19 @@ rb_ary_equal(VALUE ary1, VALUE ary2)
return rb_exec_recursive(recursive_equal, ary1, ary2);
}
+static VALUE
+recursive_eql(VALUE ary1, VALUE ary2, int recur)
+{
+ long i;
+
+ if (recur) return Qfalse;
+ for (i=0; i<RARRAY_LEN(ary1); i++) {
+ if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
+ return Qfalse;
+ }
+ return Qtrue;
+}
+
/*
* call-seq:
* array.eql?(other) -> true or false
@@ -2354,16 +2367,10 @@ rb_ary_equal(VALUE ary1, VALUE ary2)
static VALUE
rb_ary_eql(VALUE ary1, VALUE ary2)
{
- long i;
-
if (ary1 == ary2) return Qtrue;
if (TYPE(ary2) != T_ARRAY) return Qfalse;
if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
- for (i=0; i<RARRAY_LEN(ary1); i++) {
- if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
- return Qfalse;
- }
- return Qtrue;
+ return rb_exec_recursive(recursive_eql, ary1, ary2);
}
static VALUE
@@ -2425,6 +2432,25 @@ rb_ary_includes(VALUE ary, VALUE item)
}
+static VALUE
+recursive_cmp(VALUE ary1, VALUE ary2, int recur)
+{
+ long i, len;
+
+ if (recur) return Qnil;
+ len = RARRAY_LEN(ary1);
+ if (len > RARRAY_LEN(ary2)) {
+ len = RARRAY_LEN(ary2);
+ }
+ for (i=0; i<RARRAY_LEN(ary1); i++) {
+ VALUE v = rb_funcall(rb_ary_elt(ary1, i), id_cmp, 1, rb_ary_elt(ary2, i));
+ if (v != INT2FIX(0)) {
+ return v;
+ }
+ }
+ return Qundef;
+}
+
/*
* call-seq:
* array <=> other_array -> -1, 0, +1
@@ -2448,19 +2474,13 @@ rb_ary_includes(VALUE ary, VALUE item)
VALUE
rb_ary_cmp(VALUE ary1, VALUE ary2)
{
- long i, len;
+ long len;
+ VALUE v;
ary2 = to_ary(ary2);
- len = RARRAY_LEN(ary1);
- if (len > RARRAY_LEN(ary2)) {
- len = RARRAY_LEN(ary2);
- }
- for (i=0; i<len; i++) {
- VALUE v = rb_funcall(rb_ary_elt(ary1, i), id_cmp, 1, rb_ary_elt(ary2, i));
- if (v != INT2FIX(0)) {
- return v;
- }
- }
+ if (ary1 == ary2) return INT2FIX(0);
+ v = rb_exec_recursive(recursive_cmp, ary1, ary2);
+ if (v != Qundef) return v;
len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
if (len == 0) return INT2FIX(0);
if (len > 0) return INT2FIX(1);