From ba19ba779cc232474d75eb190e7420bf667832dc Mon Sep 17 00:00:00 2001 From: matz Date: Tue, 21 Sep 2004 09:35:29 +0000 Subject: * array.c (rb_ary_uniq_bang): element size might change during comparison. [ruby-dev:24298] * enum.c (enum_sort_by): do not use qsort directly. use rb_ary_sort_bang() instead. [ruby-dev:24291] * enum.c (enum_sort_by): pedantic type check added. [ruby-dev:24291] * hash.c (rb_hash_foreach_iter): check iter_lev after each iteration. [ruby-dev:24289] * array.c (rb_ary_and): element size might change during comparison. [ruby-dev:24290] * array.c (rb_ary_or): ditto. [ruby-dev:24292] * array.c (rb_ary_equal): wrong fix. [ruby-dev:24286] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@6940 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- array.c | 94 +++++++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 63 insertions(+), 31 deletions(-) (limited to 'array.c') diff --git a/array.c b/array.c index 67da6b8e7e..3e22138468 100644 --- a/array.c +++ b/array.c @@ -561,23 +561,30 @@ rb_ary_unshift_m(argc, argv, ary) return ary; } -VALUE -rb_ary_entry(ary, offset) +/* faster version - use this if you don't need to treat negative offset */ +static inline VALUE +rb_ary_elt(ary, offset) VALUE ary; long offset; { if (RARRAY(ary)->len == 0) return Qnil; - - if (offset < 0) { - offset += RARRAY(ary)->len; - } if (offset < 0 || RARRAY(ary)->len <= offset) { return Qnil; } - return RARRAY(ary)->ptr[offset]; } +VALUE +rb_ary_entry(ary, offset) + VALUE ary; + long offset; +{ + if (offset < 0) { + offset += RARRAY(ary)->len; + } + return rb_ary_elt(ary, offset); +} + static VALUE rb_ary_subseq(ary, beg, len) VALUE ary; @@ -857,6 +864,10 @@ rb_ary_index(ary, val) * array.rindex(obj) -> int or nil * * Returns the index of the last object in array + if (i > RARRAY(ary)->len) { + i = RARRAY(ary)->len; + continue; + } * == to obj. Returns nil if * no match is found. * @@ -1533,17 +1544,36 @@ rb_ary_reverse_m(ary) return rb_ary_reverse(rb_ary_dup(ary)); } +struct ary_sort_data { + VALUE ary; + VALUE *ptr; + long len; +}; + +static void +ary_sort_check(data) + struct ary_sort_data *data; +{ + if (RARRAY(data->ary)->ptr != data->ptr || RARRAY(data->ary)->len != data->len) { + rb_raise(rb_eArgError, "array modified during sort"); + } +} + static int -sort_1(a, b) +sort_1(a, b, data) VALUE *a, *b; + struct ary_sort_data *data; { VALUE retval = rb_yield_values(2, *a, *b); + + ary_sort_check(data); return rb_cmpint(retval, *a, *b); } static int -sort_2(ap, bp) +sort_2(ap, bp, data) VALUE *ap, *bp; + struct ary_sort_data *data; { VALUE retval; long a = (long)*ap, b = (long)*bp; @@ -1558,6 +1588,7 @@ sort_2(ap, bp) } retval = rb_funcall(a, id_cmp, 1, b); + ary_sort_check(data); return rb_cmpint(retval, a, b); } @@ -1565,8 +1596,12 @@ static VALUE sort_internal(ary) VALUE ary; { + struct ary_sort_data data; + + data.ary = ary; + data.ptr = RARRAY(ary)->ptr; data.len = RARRAY(ary)->len; qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE), - rb_block_given_p()?sort_1:sort_2); + rb_block_given_p()?sort_1:sort_2, &data); return ary; } @@ -1775,7 +1810,7 @@ rb_ary_select(argc, argv, ary) result = rb_ary_new2(RARRAY(ary)->len); for (i = 0; i < RARRAY(ary)->len; i++) { if (RTEST(rb_yield(RARRAY(ary)->ptr[i]))) { - rb_ary_push(result, rb_ary_entry(ary, i)); + rb_ary_push(result, rb_ary_elt(ary, i)); } } return result; @@ -2038,9 +2073,9 @@ rb_ary_zip(argc, argv, ary) for (i=0; ilen; i++) { VALUE tmp = rb_ary_new2(argc+1); - rb_ary_push(tmp, rb_ary_entry(ary, i)); + rb_ary_push(tmp, rb_ary_elt(ary, i)); for (j=0; jlen; if (alen == 0) return rb_ary_dup(ary); for (i=0; ilen; result = rb_ary_new2(elen); @@ -2094,7 +2129,7 @@ rb_ary_transpose(ary) RARRAY(tmp)->len, elen); } for (j=0; jlen; i++) { if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse; - if (!rb_equal(RARRAY(ary1)->ptr[i], RARRAY(ary2)->ptr[i])) + if (!rb_equal(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i))) return Qfalse; } return Qtrue; @@ -2640,7 +2675,7 @@ rb_ary_and(ary1, ary2) for (i=0; ilen; i++) { VALUE v = RARRAY(ary1)->ptr[i]; if (st_delete(RHASH(hash)->tbl, (st_data_t*)&v, 0)) { - rb_ary_push(ary3, RARRAY(ary1)->ptr[i]); + rb_ary_push(ary3, rb_ary_elt(ary1, i)); } } @@ -2671,15 +2706,15 @@ rb_ary_or(ary1, ary2) hash = ary_make_hash(ary1, ary2); for (i=0; ilen; i++) { - v = RARRAY(ary1)->ptr[i]; + v = rb_ary_elt(ary1, i); if (st_delete(RHASH(hash)->tbl, (st_data_t*)&v, 0)) { - rb_ary_push(ary3, RARRAY(ary1)->ptr[i]); + rb_ary_push(ary3, v); } } for (i=0; ilen; i++) { - v = RARRAY(ary2)->ptr[i]; + v = rb_ary_elt(ary2, i); if (st_delete(RHASH(hash)->tbl, (st_data_t*)&v, 0)) { - rb_ary_push(ary3, RARRAY(ary2)->ptr[i]); + rb_ary_push(ary3, v); } } return ary3; @@ -2704,7 +2739,7 @@ rb_ary_uniq_bang(ary) VALUE ary; { VALUE hash; - VALUE *p, *q, *end; + long i, j; rb_ary_modify(ary); @@ -2713,16 +2748,13 @@ rb_ary_uniq_bang(ary) if (RARRAY(ary)->len == RHASH(hash)->tbl->num_entries) { return Qnil; } - p = q = RARRAY(ary)->ptr; - end = p + RARRAY(ary)->len; - while (p < end) { - VALUE v = *p; + for (i=j=0; ilen; i++) { + VALUE v = rb_ary_elt(ary, i); if (st_delete(RHASH(hash)->tbl, (st_data_t*)&v, 0)) { - *q++ = *p; + rb_ary_store(ary, j++, v); } - p++; } - RARRAY(ary)->len = (q - RARRAY(ary)->ptr); + RARRAY(ary)->len = j; return ary; } -- cgit v1.2.1