diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-09-21 09:35:29 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2004-09-21 09:35:29 +0000 |
commit | ba19ba779cc232474d75eb190e7420bf667832dc (patch) | |
tree | ac9f317f71df73b44ce9a4b0b485f6df646d44bc | |
parent | de5a85496ac4ae7bd24b5fc7acb8001a5e4d8b7d (diff) |
* 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
-rw-r--r-- | ChangeLog | 23 | ||||
-rw-r--r-- | array.c | 94 | ||||
-rw-r--r-- | dir.c | 3 | ||||
-rw-r--r-- | enum.c | 17 | ||||
-rw-r--r-- | hash.c | 6 | ||||
-rw-r--r-- | lib/delegate.rb | 1 | ||||
-rw-r--r-- | util.c | 37 | ||||
-rw-r--r-- | util.h | 4 |
8 files changed, 124 insertions, 61 deletions
@@ -1,3 +1,26 @@ +Tue Sep 21 18:29:49 2004 Yukihiro Matsumoto <matz@ruby-lang.org> + + * array.c (rb_ary_uniq_bang): element size might change during + comparison. [ruby-dev:24298] + +Mon Sep 20 00:24:19 2004 Yukihiro Matsumoto <matz@ruby-lang.org> + + * 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] + Sat Sep 18 15:02:22 2004 Yukihiro Matsumoto <matz@ruby-lang.org> * array.c (rb_ary_equal): element size might change during @@ -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 <i>array</i> + if (i > RARRAY(ary)->len) { + i = RARRAY(ary)->len; + continue; + } * <code>==</code> to <i>obj</i>. Returns <code>nil</code> 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; i<RARRAY(ary)->len; 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; j<argc; j++) { - rb_ary_push(tmp, rb_ary_entry(argv[j], i)); + rb_ary_push(tmp, rb_ary_elt(argv[j], i)); } rb_yield(tmp); } @@ -2051,9 +2086,9 @@ rb_ary_zip(argc, argv, ary) for (i=0; i<len; 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; j<argc; j++) { - rb_ary_push(tmp, rb_ary_entry(argv[j], i)); + rb_ary_push(tmp, rb_ary_elt(argv[j], i)); } rb_ary_push(result, tmp); } @@ -2081,7 +2116,7 @@ rb_ary_transpose(ary) alen = RARRAY(ary)->len; if (alen == 0) return rb_ary_dup(ary); for (i=0; i<alen; i++) { - tmp = to_ary(rb_ary_entry(ary, i)); + tmp = to_ary(rb_ary_elt(ary, i)); if (elen < 0) { /* first element */ elen = RARRAY(tmp)->len; result = rb_ary_new2(elen); @@ -2094,7 +2129,7 @@ rb_ary_transpose(ary) RARRAY(tmp)->len, elen); } for (j=0; j<elen; j++) { - rb_ary_store(rb_ary_entry(result, j), i, rb_ary_entry(tmp, j)); + rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j)); } } return result; @@ -2441,7 +2476,7 @@ rb_ary_equal(ary1, ary2) } for (i=0; i<RARRAY(ary1)->len; 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; i<RARRAY(ary1)->len; 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; i<RARRAY(ary1)->len; 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; i<RARRAY(ary2)->len; 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; i<RARRAY(ary)->len; 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; } @@ -648,8 +648,9 @@ dir_s_chdir(argc, argv, obj) if (rb_block_given_p()) { struct chdir_data args; + char *cwd = my_getcwd(); - args.old_path = rb_str_new2(my_getcwd()); + args.old_path = rb_tainted_str_new2(cwd); free(cwd); args.new_path = path; args.done = Qfalse; return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args); @@ -397,14 +397,17 @@ sort_by_i(i, ary) return Qnil; } -static int -sort_by_cmp(a, b) - VALUE *a, *b; +static VALUE +sort_by_cmp(values, ary) + VALUE values; { - VALUE retval; + VALUE a = RARRAY(values)->ptr[0]; + VALUE b = RARRAY(values)->ptr[1]; - retval = rb_funcall(RARRAY(*a)->ptr[0], id_cmp, 1, RARRAY(*b)->ptr[0]); - return rb_cmpint(retval, *a, *b); + /* pedantic check; they must be arrays */ + Check_Type(a, T_ARRAY); + Check_Type(b, T_ARRAY); + return rb_funcall(RARRAY(a)->ptr[0], id_cmp, 1, RARRAY(b)->ptr[0]); } /* @@ -491,7 +494,7 @@ enum_sort_by(obj) } rb_iterate(rb_each, obj, sort_by_i, ary); if (RARRAY(ary)->len > 1) { - qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE), sort_by_cmp); + rb_iterate(rb_ary_sort_bang, ary, sort_by_cmp, ary); } for (i=0; i<RARRAY(ary)->len; i++) { VALUE e = RARRAY(ary)->ptr[i]; @@ -131,9 +131,13 @@ rb_hash_foreach_iter(key, value, arg) if (key == Qundef) return ST_CONTINUE; status = (*arg->func)(key, value, arg->arg); - if (RHASH(arg->hash)->tbl != tbl || RHASH(arg->hash)->tbl->bins != bins){ + if (RHASH(arg->hash)->tbl != tbl || + RHASH(arg->hash)->tbl->bins != bins) { rb_raise(rb_eIndexError, "rehash occurred during iteration"); } + if (RHASH(arg->hash)->iter_lev == 0) { + rb_raise(rb_eArgError, "block re-entered"); + } return status; } diff --git a/lib/delegate.rb b/lib/delegate.rb index 122a565642..a14d62cf5b 100644 --- a/lib/delegate.rb +++ b/lib/delegate.rb @@ -92,7 +92,6 @@ def DelegateClass(superclass) @_dc_obj = obj end def method_missing(m, *args) - p [m, *args] unless @_dc_obj.respond_to?(m) super(m, *args) end @@ -466,15 +466,16 @@ typedef struct { char *LL, *RR; } stack_node; /* Stack structure for L,l,R,r */ #define PUSH(ll,rr) do { top->LL = (ll); top->RR = (rr); ++top; } while (0) /* Push L,l,R,r */ #define POP(ll,rr) do { --top; ll = top->LL; rr = top->RR; } while (0) /* Pop L,l,R,r */ -#define med3(a,b,c) ((*cmp)(a,b)<0 ? \ - ((*cmp)(b,c)<0 ? b : ((*cmp)(a,c)<0 ? c : a)) : \ - ((*cmp)(b,c)>0 ? b : ((*cmp)(a,c)<0 ? a : c))) +#define med3(a,b,c) ((*cmp)(a,b,d)<0 ? \ + ((*cmp)(b,c,d)<0 ? b : ((*cmp)(a,c,d)<0 ? c : a)) : \ + ((*cmp)(b,c,d)>0 ? b : ((*cmp)(a,c,d)<0 ? a : c))) -void ruby_qsort (base, nel, size, cmp) +void ruby_qsort (base, nel, size, cmp, d) void* base; const int nel; const int size; int (*cmp)(); + void *d; { register char *l, *r, *m; /* l,r:left,right group m:median point */ register int t, eq_l, eq_r; /* eq_l: all items in left group are equal to S */ @@ -495,7 +496,7 @@ void ruby_qsort (base, nel, size, cmp) for (;;) { start: if (L + size == R) { /* 2 elements */ - if ((*cmp)(L,R) > 0) mmswap(L,R); goto nxt; + if ((*cmp)(L,R,d) > 0) mmswap(L,R); goto nxt; } l = L; r = R; @@ -526,49 +527,49 @@ void ruby_qsort (base, nel, size, cmp) m = med3(m1, m, m3); } - if ((t = (*cmp)(l,m)) < 0) { /*3-5-?*/ - if ((t = (*cmp)(m,r)) < 0) { /*3-5-7*/ + if ((t = (*cmp)(l,m,d)) < 0) { /*3-5-?*/ + if ((t = (*cmp)(m,r,d)) < 0) { /*3-5-7*/ if (chklim && nel >= chklim) { /* check if already ascending order */ char *p; chklim = 0; - for (p=l; p<r; p+=size) if ((*cmp)(p,p+size) > 0) goto fail; + for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) > 0) goto fail; goto nxt; } fail: goto loopA; /*3-5-7*/ } if (t > 0) { - if ((*cmp)(l,r) <= 0) {mmswap(m,r); goto loopA;} /*3-5-4*/ + if ((*cmp)(l,r,d) <= 0) {mmswap(m,r); goto loopA;} /*3-5-4*/ mmrot3(r,m,l); goto loopA; /*3-5-2*/ } goto loopB; /*3-5-5*/ } if (t > 0) { /*7-5-?*/ - if ((t = (*cmp)(m,r)) > 0) { /*7-5-3*/ + if ((t = (*cmp)(m,r,d)) > 0) { /*7-5-3*/ if (chklim && nel >= chklim) { /* check if already ascending order */ char *p; chklim = 0; - for (p=l; p<r; p+=size) if ((*cmp)(p,p+size) < 0) goto fail2; + for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) < 0) goto fail2; while (l<r) {mmswap(l,r); l+=size; r-=size;} /* reverse region */ goto nxt; } fail2: mmswap(l,r); goto loopA; /*7-5-3*/ } if (t < 0) { - if ((*cmp)(l,r) <= 0) {mmswap(l,m); goto loopB;} /*7-5-8*/ + if ((*cmp)(l,r,d) <= 0) {mmswap(l,m); goto loopB;} /*7-5-8*/ mmrot3(l,m,r); goto loopA; /*7-5-6*/ } mmswap(l,r); goto loopA; /*7-5-5*/ } - if ((t = (*cmp)(m,r)) < 0) {goto loopA;} /*5-5-7*/ + if ((t = (*cmp)(m,r,d)) < 0) {goto loopA;} /*5-5-7*/ if (t > 0) {mmswap(l,r); goto loopB;} /*5-5-3*/ /* determining splitting type in case 5-5-5 */ /*5-5-5*/ for (;;) { if ((l += size) == r) goto nxt; /*5-5-5*/ if (l == m) continue; - if ((t = (*cmp)(l,m)) > 0) {mmswap(l,r); l = L; goto loopA;} /*575-5*/ + if ((t = (*cmp)(l,m,d)) > 0) {mmswap(l,r); l = L; goto loopA;}/*575-5*/ if (t < 0) {mmswap(L,l); l = L; goto loopB;} /*535-5*/ } @@ -578,14 +579,14 @@ void ruby_qsort (base, nel, size, cmp) if ((l += size) == r) {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;} if (l == m) continue; - if ((t = (*cmp)(l,m)) > 0) {eq_r = 0; break;} + if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;} if (t < 0) eq_l = 0; } for (;;) { if (l == (r -= size)) {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;} if (r == m) {m = l; break;} - if ((t = (*cmp)(r,m)) < 0) {eq_l = 0; break;} + if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;} if (t == 0) break; } mmswap(l,r); /* swap left and right */ @@ -597,14 +598,14 @@ void ruby_qsort (base, nel, size, cmp) if (l == (r -= size)) {r += size; if (r != m) mmswap(r,m); r += size; goto fin;} if (r == m) continue; - if ((t = (*cmp)(r,m)) < 0) {eq_l = 0; break;} + if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;} if (t > 0) eq_r = 0; } for (;;) { if ((l += size) == r) {r += size; if (r != m) mmswap(r,m); r += size; goto fin;} if (l == m) {m = r; break;} - if ((t = (*cmp)(l,m)) > 0) {eq_r = 0; break;} + if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;} if (t == 0) break; } mmswap(l,r); /* swap left and right */ @@ -43,8 +43,8 @@ unsigned long scan_hex _((const char*, int, int*)); void ruby_add_suffix(); #endif -void ruby_qsort _((void*, const int, const int, int (*)())); -#define qsort(b,n,s,c) ruby_qsort(b,n,s,c) +void ruby_qsort _((void*, const int, const int, int (*)(), void*)); +#define qsort(b,n,s,c,d) ruby_qsort(b,n,s,c,d) void ruby_setenv _((const char*, const char*)); void ruby_unsetenv _((const char*)); |