From 6f9dcadf6e46c80bb1f807f88a691cfe388f4f8b Mon Sep 17 00:00:00 2001 From: matz Date: Sat, 2 Oct 2004 03:50:53 +0000 Subject: * string.c (rb_str_sum): check was done with false pointer. [ruby-dev:24383] * string.c (rb_str_sum): string may be altered. [ruby-dev:24381] * eval.c (rb_f_eval): defer pointer retrieval to prevent unsafe sourcefile string modification. [ruby-dev:24373] * io.c (io_read): block string buffer modification during rb_io_fread() by freezing it temporarily. [ruby-dev:24366] * io.c (rb_io_s_popen): mode argument may be altered. [ruby-dev:24375] * file.c (rb_file_s_basename): ext argument may be altered. [ruby-dev:24377] * enum.c (enum_sort_by): use NODE instead of 2 element arrays. [ruby-dev:24378] * string.c (rb_str_chomp_bang): StringValue() may change the receiver. [ruby-dev:24371] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@6979 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 57 ++++++++++++++++++++++++ array.c | 57 +++++++++++++++--------- enum.c | 25 +++++------ eval.c | 15 +++++-- ext/socket/socket.c | 2 + file.c | 11 +++-- hash.c | 116 ++++++++++++++++++++++++++++++++----------------- intern.h | 2 + io.c | 6 ++- marshal.c | 4 +- object.c | 2 +- process.c | 2 +- re.c | 4 +- string.c | 48 +++++++++++++++----- struct.c | 123 +++++++++++++++++++++++++++++----------------------- variable.c | 14 +++--- 16 files changed, 328 insertions(+), 160 deletions(-) diff --git a/ChangeLog b/ChangeLog index d4ada9f45e..12856007b7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +Sat Oct 2 00:42:20 2004 Yukihiro Matsumoto + + * string.c (rb_str_sum): check was done with false pointer. + [ruby-dev:24383] + + * string.c (rb_str_sum): string may be altered. [ruby-dev:24381] + +Fri Oct 1 11:40:14 2004 Yukihiro Matsumoto + + * eval.c (rb_f_eval): defer pointer retrieval to prevent unsafe + sourcefile string modification. [ruby-dev:24373] + + * io.c (io_read): block string buffer modification during + rb_io_fread() by freezing it temporarily. [ruby-dev:24366] + + * io.c (rb_io_s_popen): mode argument may be altered. + [ruby-dev:24375] + + * file.c (rb_file_s_basename): ext argument may be altered. + [ruby-dev:24377] + + * enum.c (enum_sort_by): use NODE instead of 2 element arrays. + [ruby-dev:24378] + + * string.c (rb_str_chomp_bang): StringValue() may change the + receiver. [ruby-dev:24371] + Fri Oct 1 11:25:20 2004 Hidetoshi NAGAI * ext/tk/lib/tk/grid.rb: revive TkGrid.grid @@ -22,6 +49,36 @@ Wed Sep 29 10:58:07 2004 Nobuyoshi Nakada * enum.c (sort_by_i): internally used object must not be changed outside. [ruby-dev:24368] +Mon Sep 27 09:14:03 2004 Yukihiro Matsumoto + + * ext/socket/socket.c (s_accept): don't retry for EWOULDBLOCK. + [ruby-talk:113807] + +Fri Sep 24 16:09:42 2004 Yukihiro Matsumoto + + * eval.c (proc_invoke): propagate DVAR_DONT_RECYCLE on termination + to avoid double call to rb_gc_force_recycle(). [ruby-dev:24311] + +Fri Sep 24 08:29:45 2004 Yukihiro Matsumoto + + * array.c (rb_ary_subseq): original object might be modified after + sharing data creation. [ruby-dev:24327] + + * array.c (rb_ary_replace): ditto. + + * array.c (ary_make_shared): freeze shared array. [ruby-dev:24325] + + * struct.c (struct_members): always check struct size and size of + members list in the class. [ruby-dev:24320] + +Thu Sep 23 09:29:14 2004 Yukihiro Matsumoto + + * string.c (rb_str_sub_bang): check if string is not modified + during iteration. [ruby-dev:24315] + + * hash.c (rb_hash_rehash): replace st_foreach() by its deep + checking counterpart. [ruby-dev:24310] + Wed Sep 22 13:38:12 2004 Yukihiro Matsumoto * hash.c (rb_hash_rehash): add iteration check. [ruby-dev:24301] diff --git a/array.c b/array.c index da32a8984e..7afc1301b5 100644 --- a/array.c +++ b/array.c @@ -459,7 +459,7 @@ rb_ary_pop(ary) return RARRAY(ary)->ptr[--RARRAY(ary)->len]; } -static void +static VALUE ary_make_shared(ary) VALUE ary; { @@ -472,6 +472,11 @@ ary_make_shared(ary) shared->aux.capa = RARRAY(ary)->aux.capa; RARRAY(ary)->aux.shared = (VALUE)shared; FL_SET(ary, ELTS_SHARED); + OBJ_FREEZE(shared); + return (VALUE)shared; + } + else { + return RARRAY(ary)->aux.shared; } } @@ -591,7 +596,8 @@ rb_ary_subseq(ary, beg, len) VALUE ary; long beg, len; { - VALUE klass, ary2; + VALUE klass, ary2, shared; + VALUE *ptr; if (beg > RARRAY(ary)->len) return Qnil; if (beg < 0 || len < 0) return Qnil; @@ -604,11 +610,12 @@ rb_ary_subseq(ary, beg, len) klass = rb_obj_class(ary); if (len == 0) return ary_new(klass, 0); - ary_make_shared(ary); + shared = ary_make_shared(ary); + ptr = RARRAY(ary)->ptr; ary2 = ary_alloc(klass); - RARRAY(ary2)->ptr = RARRAY(ary)->ptr + beg; + RARRAY(ary2)->ptr = ptr + beg; RARRAY(ary2)->len = len; - RARRAY(ary2)->aux.shared = RARRAY(ary)->aux.shared; + RARRAY(ary2)->aux.shared = shared; FL_SET(ary2, ELTS_SHARED); return ary2; @@ -1562,9 +1569,10 @@ sort_1(a, b, data) struct ary_sort_data *data; { VALUE retval = rb_yield_values(2, *a, *b); + int n; - ary_sort_check(data); - return rb_cmpint(retval, *a, *b); + n = rb_cmpint(retval, *a, *b); + return n; } static int @@ -1573,11 +1581,12 @@ sort_2(ap, bp, data) struct ary_sort_data *data; { VALUE retval; - long a = (long)*ap, b = (long)*bp; + VALUE a = *ap, b = *bp; + int n; if (FIXNUM_P(a) && FIXNUM_P(b)) { - if (a > b) return 1; - if (a < b) return -1; + if ((long)a > (long)b) return 1; + if ((long)a < (long)b) return -1; return 0; } if (TYPE(a) == T_STRING && TYPE(b) == T_STRING) { @@ -1585,8 +1594,9 @@ sort_2(ap, bp, data) } retval = rb_funcall(a, id_cmp, 1, b); - ary_sort_check(data); - return rb_cmpint(retval, a, b); + n = rb_cmpint(retval, a, b); + + return n; } static VALUE @@ -2150,15 +2160,17 @@ static VALUE rb_ary_replace(copy, orig) VALUE copy, orig; { + VALUE shared; + rb_ary_modify(copy); orig = to_ary(orig); if (copy == orig) return copy; - ary_make_shared(orig); + shared = ary_make_shared(orig); if (RARRAY(copy)->ptr && !FL_TEST(copy, ELTS_SHARED)) free(RARRAY(copy)->ptr); - RARRAY(copy)->ptr = RARRAY(orig)->ptr; - RARRAY(copy)->len = RARRAY(orig)->len; - RARRAY(copy)->aux.shared = RARRAY(orig)->aux.shared; + RARRAY(copy)->ptr = RARRAY(shared)->ptr; + RARRAY(copy)->len = RARRAY(shared)->len; + RARRAY(copy)->aux.shared = shared; FL_SET(copy, ELTS_SHARED); return copy; @@ -2874,8 +2886,11 @@ flatten(ary, idx, ary2, memo) rb_ary_push(memo, id); rb_ary_update(ary, idx, 1, ary2); while (i < lim) { - if (TYPE(RARRAY(ary)->ptr[i]) == T_ARRAY) { - n = flatten(ary, i, RARRAY(ary)->ptr[i], memo); + VALUE tmp; + + tmp = rb_check_array_type(RARRAY(ary)->ptr[i]); + if (!NIL_P(tmp)) { + n = flatten(ary, i, tmp, memo); i += n; lim += n; } i++; @@ -2910,12 +2925,14 @@ rb_ary_flatten_bang(ary) rb_ary_modify(ary); while (ilen) { VALUE ary2 = RARRAY(ary)->ptr[i]; + VALUE tmp; - if (TYPE(ary2) == T_ARRAY) { + tmp = rb_check_array_type(ary2); + if (!NIL_P(tmp)) { if (NIL_P(memo)) { memo = rb_ary_new(); } - i += flatten(ary, i, ary2, memo); + i += flatten(ary, i, tmp, memo); mod = 1; } i++; diff --git a/enum.c b/enum.c index 67d6ee8bf3..f72c682107 100644 --- a/enum.c +++ b/enum.c @@ -389,26 +389,26 @@ static VALUE sort_by_i(i, ary) VALUE i, ary; { - VALUE v, e; + VALUE v; + NODE *memo; v = rb_yield(i); - e = rb_assoc_new(v, i); - OBJ_FREEZE(e); - rb_ary_push(ary, e); + memo = rb_node_newnode(NODE_MEMO, v, i, 0); + rb_ary_push(ary, (VALUE)memo); return Qnil; } static VALUE sort_by_cmp(values, ary) - VALUE values; + VALUE values, ary; { - VALUE a = RARRAY(values)->ptr[0]; - VALUE b = RARRAY(values)->ptr[1]; + NODE *a = (NODE*)RARRAY(values)->ptr[0]; + NODE *b = (NODE*)RARRAY(values)->ptr[1]; - /* 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]); + /* pedantic check; they must be memo nodes */ + Check_Type(a, T_NODE); + Check_Type(b, T_NODE); + return rb_funcall(a->u1.value, id_cmp, 1, b->u1.value); } /* @@ -498,8 +498,7 @@ enum_sort_by(obj) rb_iterate(rb_ary_sort_bang, ary, sort_by_cmp, ary); } for (i=0; ilen; i++) { - VALUE e = RARRAY(ary)->ptr[i]; - RARRAY(ary)->ptr[i] = RARRAY(e)->ptr[1]; + RARRAY(ary)->ptr[i] = RNODE(RARRAY(ary)->ptr[i])->u2.value; } return ary; } diff --git a/eval.c b/eval.c index 040284f4b8..65a91587a3 100644 --- a/eval.c +++ b/eval.c @@ -6187,12 +6187,13 @@ rb_f_eval(argc, argv, self) SafeStringValue(src); } if (argc >= 3) { - file = StringValuePtr(vfile); + StringValue(vfile); } if (argc >= 4) { line = NUM2INT(vline); } + if (!NIL_P(vfile)) file = RSTRING(vfile)->ptr; if (NIL_P(scope) && ruby_frame->prev) { struct FRAME *prev; VALUE val; @@ -8096,6 +8097,14 @@ proc_invoke(proc, args, self, klass) POP_ITER(); ruby_block = old_block; ruby_wrapper = old_wrapper; + if (FL_TEST(ruby_dyna_vars, DVAR_DONT_RECYCLE)) { + struct RVarmap *vars; + + for (vars = old_dvars; vars; vars = vars->next) { + if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break; + FL_SET(vars, DVAR_DONT_RECYCLE); + } + } ruby_dyna_vars = old_dvars; ruby_safe_level = safe; @@ -12076,6 +12085,7 @@ rb_callcc(self) volatile rb_thread_t th_save; struct tag *tag; struct RVarmap *vars; + struct BLOCK *blk; THREAD_ALLOC(th); cont = Data_Wrap_Struct(rb_cCont, thread_mark, thread_free, th); @@ -12086,11 +12096,10 @@ rb_callcc(self) } th->thread = curr_thread->thread; - for (vars = th->dyna_vars; vars; vars = vars->next) { + for (vars = ruby_dyna_vars; vars; vars = vars->next) { if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break; FL_SET(vars, DVAR_DONT_RECYCLE); } - th_save = th; if (THREAD_SAVE_CONTEXT(th)) { return th_save->result; diff --git a/ext/socket/socket.c b/ext/socket/socket.c index 6faeb19177..21f2bea5d3 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -1168,6 +1168,8 @@ s_accept(klass, fd, sockaddr, len) rb_gc(); retry = 1; goto retry; + case EWOULDBLOCK: + break; default: if (!rb_io_wait_readable(fd)) break; retry = 0; diff --git a/file.c b/file.c index a66e444543..ffa70c6093 100644 --- a/file.c +++ b/file.c @@ -1644,8 +1644,7 @@ rb_file_s_lchmod(argc, argv) { VALUE vmode; VALUE rest; - int mode; - long n; + long mode, n; rb_secure(2); rb_scan_args(argc, argv, "1*", &vmode, &rest); @@ -2560,11 +2559,11 @@ rb_file_s_basename(argc, argv) VALUE *argv; { VALUE fname, fext, basename; - char *name, *p, *ext = NULL; + char *name, *p; int f; if (rb_scan_args(argc, argv, "11", &fname, &fext) == 2) { - ext = StringValueCStr(fext); + StringValue(fext); } StringValue(fname); if (RSTRING(fname)->len == 0 || !*(name = RSTRING(fname)->ptr)) @@ -2580,7 +2579,7 @@ rb_file_s_basename(argc, argv) #endif } else if (!(p = strrdirsep(name))) { - if (NIL_P(fext) || !(f = rmext(name, ext))) { + if (NIL_P(fext) || !(f = rmext(name, StringValueCStr(fext)))) { f = chompdirsep(name) - name; if (f == RSTRING(fname)->len) return fname; } @@ -2588,7 +2587,7 @@ rb_file_s_basename(argc, argv) } else { while (isdirsep(*p)) p++; /* skip last / */ - if (NIL_P(fext) || !(f = rmext(p, ext))) { + if (NIL_P(fext) || !(f = rmext(p, StringValueCStr(fext)))) { f = chompdirsep(p) - p; } } diff --git a/hash.c b/hash.c index 4485305024..fbf8d5d20d 100644 --- a/hash.c +++ b/hash.c @@ -114,16 +114,54 @@ static struct st_hash_type objhash = { rb_any_hash, }; -struct rb_hash_foreach_arg { +struct foreach_safe_arg { + st_table *tbl; + int (*func)(); + st_data_t arg; +}; + +static int +foreach_safe_i(key, value, arg, err) + st_data_t key, value; + struct foreach_safe_arg *arg; +{ + int status; + + if (err) { + rb_raise(rb_eRuntimeError, "hash modified during iteration"); + } + if (key == Qundef) return ST_CONTINUE; + status = (*arg->func)(key, value, arg->arg, err); + if (status == ST_CONTINUE) { + return ST_CHECK; + } + return status; +} + +void +st_foreach_safe(table, func, a) + st_table *table; + int (*func)(); + st_data_t a; +{ + struct foreach_safe_arg arg; + + arg.tbl = table; + arg.func = func; + arg.arg = a; + st_foreach(table, foreach_safe_i, (st_data_t)&arg); +} + +struct hash_foreach_arg { VALUE hash; - enum st_retval (*func)(); + int (*func)(); VALUE arg; }; static int -rb_hash_foreach_iter(key, value, arg, err) +hash_foreach_iter(key, value, arg, err) VALUE key, value; - struct rb_hash_foreach_arg *arg; + struct hash_foreach_arg *arg; int err; { int status; @@ -151,15 +189,7 @@ rb_hash_foreach_iter(key, value, arg, err) } static VALUE -rb_hash_foreach_call(arg) - struct rb_hash_foreach_arg *arg; -{ - st_foreach(RHASH(arg->hash)->tbl, rb_hash_foreach_iter, (st_data_t)arg); - return Qnil; -} - -static VALUE -rb_hash_foreach_ensure(hash) +hash_foreach_ensure(hash) VALUE hash; { RHASH(hash)->iter_lev--; @@ -173,19 +203,27 @@ rb_hash_foreach_ensure(hash) return 0; } -static int +static VALUE +hash_foreach_call(arg) + struct hash_foreach_arg *arg; +{ + st_foreach(RHASH(arg->hash)->tbl, hash_foreach_iter, (st_data_t)arg); + return Qnil; +} + +void rb_hash_foreach(hash, func, farg) VALUE hash; - enum st_retval (*func)(); + int (*func)(); VALUE farg; { - struct rb_hash_foreach_arg arg; + struct hash_foreach_arg arg; RHASH(hash)->iter_lev++; arg.hash = hash; arg.func = func; arg.arg = farg; - return rb_ensure(rb_hash_foreach_call, (VALUE)&arg, rb_hash_foreach_ensure, hash); + rb_ensure(hash_foreach_call, (VALUE)&arg, hash_foreach_ensure, hash); } static VALUE hash_alloc _((VALUE)); @@ -354,7 +392,7 @@ rb_hash_rehash(hash) rb_hash_modify(hash); tbl = st_init_table_with_size(&objhash, RHASH(hash)->tbl->num_entries); - st_foreach(RHASH(hash)->tbl, rb_hash_rehash_i, (st_data_t)tbl); + rb_hash_foreach(hash, rb_hash_rehash_i, (st_data_t)tbl); st_free_table(RHASH(hash)->tbl); RHASH(hash)->tbl = tbl; @@ -566,7 +604,7 @@ rb_hash_index(hash, value) args[0] = value; args[1] = Qnil; - st_foreach(RHASH(hash)->tbl, index_i, (st_data_t)args); + rb_hash_foreach(hash, index_i, (st_data_t)args); return args[1]; } @@ -678,7 +716,7 @@ rb_hash_shift(hash) rb_hash_modify(hash); var.stop = 0; - st_foreach(RHASH(hash)->tbl, shift_i, (st_data_t)&var); + rb_hash_foreach(hash, shift_i, (st_data_t)&var); if (var.stop) { return rb_assoc_new(var.key, var.val); @@ -691,7 +729,7 @@ rb_hash_shift(hash) } } -static enum st_retval +static int delete_if_i(key, value, hash) VALUE key, value, hash; { @@ -758,7 +796,7 @@ rb_hash_reject(hash) return rb_hash_delete_if(rb_obj_dup(hash)); } -static enum st_retval +static int select_i(key, value, result) VALUE key, value, result; { @@ -849,7 +887,7 @@ rb_hash_clear(hash) rb_hash_modify(hash); if (RHASH(hash)->tbl->num_entries > 0) { - st_foreach(RHASH(hash)->tbl, clear_i, 0); + rb_hash_foreach(hash, clear_i, 0); } return hash; @@ -917,7 +955,7 @@ rb_hash_replace(hash, hash2) hash2 = to_hash(hash2); if (hash == hash2) return hash; rb_hash_clear(hash); - st_foreach(RHASH(hash2)->tbl, replace_i, hash); + rb_hash_foreach(hash2, replace_i, hash); RHASH(hash)->ifnone = RHASH(hash2)->ifnone; if (FL_TEST(hash2, HASH_PROC_DEFAULT)) { FL_SET(hash, HASH_PROC_DEFAULT); @@ -969,7 +1007,7 @@ rb_hash_empty_p(hash) return Qfalse; } -static enum st_retval +static int each_value_i(key, value) VALUE key, value; { @@ -1002,7 +1040,7 @@ rb_hash_each_value(hash) return hash; } -static enum st_retval +static int each_key_i(key, value) VALUE key, value; { @@ -1034,7 +1072,7 @@ rb_hash_each_key(hash) return hash; } -static enum st_retval +static int each_pair_i(key, value) VALUE key, value; { @@ -1068,7 +1106,7 @@ rb_hash_each_pair(hash) return hash; } -static enum st_retval +static int each_i(key, value) VALUE key, value; { @@ -1132,7 +1170,7 @@ rb_hash_to_a(hash) VALUE ary; ary = rb_ary_new(); - st_foreach(RHASH(hash)->tbl, to_a_i, ary); + rb_hash_foreach(hash, to_a_i, ary); if (OBJ_TAINTED(hash)) OBJ_TAINT(ary); return ary; @@ -1190,7 +1228,7 @@ inspect_hash(hash) VALUE str; str = rb_str_buf_new2("{"); - st_foreach(RHASH(hash)->tbl, inspect_i, str); + rb_hash_foreach(hash, inspect_i, str); rb_str_buf_cat2(str, "}"); OBJ_INFECT(str, hash); @@ -1284,7 +1322,7 @@ rb_hash_keys(hash) VALUE ary; ary = rb_ary_new(); - st_foreach(RHASH(hash)->tbl, keys_i, ary); + rb_hash_foreach(hash, keys_i, ary); return ary; } @@ -1317,7 +1355,7 @@ rb_hash_values(hash) VALUE ary; ary = rb_ary_new(); - st_foreach(RHASH(hash)->tbl, values_i, ary); + rb_hash_foreach(hash, values_i, ary); return ary; } @@ -1382,7 +1420,7 @@ rb_hash_has_value(hash, val) data[0] = Qfalse; data[1] = val; - st_foreach(RHASH(hash)->tbl, rb_hash_search_value, (st_data_t)data); + rb_hash_foreach(hash, rb_hash_search_value, (st_data_t)data); return data[0]; } @@ -1434,7 +1472,7 @@ hash_equal(hash1, hash2, eql) data.tbl = RHASH(hash2)->tbl; data.result = Qtrue; - st_foreach(RHASH(hash1)->tbl, equal_i, (st_data_t)&data); + rb_hash_foreach(hash1, equal_i, (st_data_t)&data); return data.result; } @@ -1509,7 +1547,7 @@ rb_hash_invert(hash) { VALUE h = rb_hash_new(); - st_foreach(RHASH(hash)->tbl, rb_hash_invert_i, h); + rb_hash_foreach(hash, rb_hash_invert_i, h); return h; } @@ -1555,10 +1593,10 @@ rb_hash_update(hash1, hash2) { hash2 = to_hash(hash2); if (rb_block_given_p()) { - st_foreach(RHASH(hash2)->tbl, rb_hash_update_block_i, hash1); + rb_hash_foreach(hash2, rb_hash_update_block_i, hash1); } else { - st_foreach(RHASH(hash2)->tbl, rb_hash_update_i, hash1); + rb_hash_foreach(hash2, rb_hash_update_i, hash1); } return hash1; } @@ -2345,7 +2383,7 @@ env_replace(env, hash) if (env == hash) return env; hash = to_hash(hash); - st_foreach(RHASH(hash)->tbl, env_replace_i, keys); + rb_hash_foreach(hash, env_replace_i, keys); for (i=0; ilen; i++) { env_delete(env, RARRAY(keys)->ptr[i]); @@ -2372,7 +2410,7 @@ env_update(env, hash) { if (env == hash) return env; hash = to_hash(hash); - st_foreach(RHASH(hash)->tbl, env_update_i, 0); + rb_hash_foreach(hash, env_update_i, 0); return env; } diff --git a/intern.h b/intern.h index 9eb521afdc..bc09ca188c 100644 --- a/intern.h +++ b/intern.h @@ -245,6 +245,8 @@ VALUE rb_gc_enable _((void)); VALUE rb_gc_disable _((void)); VALUE rb_gc_start _((void)); /* hash.c */ +void st_foreach _((struct st_table *, int (*)(), unsigned long)); +void rb_hash_foreach _((VALUE, int (*)(), VALUE)); VALUE rb_hash _((VALUE)); VALUE rb_hash_new _((void)); VALUE rb_hash_freeze _((VALUE)); diff --git a/io.c b/io.c index 09fbde48f9..83e35f23fb 100644 --- a/io.c +++ b/io.c @@ -1067,11 +1067,13 @@ io_read(argc, argv, io) StringValue(str); rb_str_modify(str); rb_str_resize(str,len); + FL_SET(str, FL_FREEZE); } if (len == 0) return str; READ_CHECK(fptr->f); n = rb_io_fread(RSTRING(str)->ptr, len, fptr->f); + FL_UNSET(str, FL_FREEZE); if (n == 0) { rb_str_resize(str,0); if (!fptr->f) return Qnil; @@ -2721,7 +2723,9 @@ rb_io_popen(str, argc, argv, klass) mode = rb_io_modenum_mode(FIX2INT(pmode), mbuf); } else { - mode = StringValuePtr(pmode); + strncpy(mbuf, StringValuePtr(pmode), sizeof(mbuf) - 1); + mbuf[sizeof(mbuf) - 1] = 0; + mode = mbuf; } SafeStringValue(pname); port = pipe_open(str, mode); diff --git a/marshal.c b/marshal.c index 90c0788b83..f4832a481f 100644 --- a/marshal.c +++ b/marshal.c @@ -437,7 +437,7 @@ w_ivar(tbl, arg) { if (tbl) { w_long(tbl->num_entries, arg->arg); - st_foreach(tbl, w_obj_each, (st_data_t)arg); + st_foreach_safe(tbl, w_obj_each, (st_data_t)arg); } else { w_long(0, arg->arg); @@ -621,7 +621,7 @@ w_object(obj, arg, limit) w_byte(TYPE_HASH_DEF, arg); } w_long(RHASH(obj)->tbl->num_entries, arg); - st_foreach(RHASH(obj)->tbl, hash_each, (st_data_t)&c_arg); + rb_hash_foreach(obj, hash_each, (st_data_t)&c_arg); if (!NIL_P(RHASH(obj)->ifnone)) { w_object(RHASH(obj)->ifnone, arg, limit); } diff --git a/object.c b/object.c index 68f768c46f..d8b0a7f569 100644 --- a/object.c +++ b/object.c @@ -404,7 +404,7 @@ static VALUE inspect_obj(obj, str) VALUE obj, str; { - st_foreach(ROBJECT(obj)->iv_tbl, inspect_i, str); + st_foreach_safe(ROBJECT(obj)->iv_tbl, inspect_i, str); rb_str_cat2(str, ">"); RSTRING(str)->ptr[0] = '#'; OBJ_INFECT(str, obj); diff --git a/process.c b/process.c index 369da9865a..b7adec401e 100644 --- a/process.c +++ b/process.c @@ -1214,8 +1214,8 @@ rb_f_exec(argc, argv) rb_raise(rb_eArgError, "wrong first argument"); } prog = RARRAY(tmp)->ptr[0]; - SafeStringValue(prog); argv[0] = RARRAY(tmp)->ptr[1]; + SafeStringValue(prog); } if (argc == 1 && prog == 0) { VALUE cmd = argv[0]; diff --git a/re.c b/re.c index acb6c1b299..5cfe7f951c 100644 --- a/re.c +++ b/re.c @@ -1681,8 +1681,6 @@ rb_reg_initialize_m(argc, argv, self) len = RREGEXP(argv[0])->len; } else { - s = StringValuePtr(argv[0]); - len = RSTRING(argv[0])->len; if (argc >= 2) { if (FIXNUM_P(argv[1])) flags = FIX2INT(argv[1]); else if (RTEST(argv[1])) flags = RE_OPTION_IGNORECASE; @@ -1708,6 +1706,8 @@ rb_reg_initialize_m(argc, argv, self) break; } } + s = StringValuePtr(argv[0]); + len = RSTRING(argv[0])->len; } rb_reg_initialize(self, s, len, flags); return self; diff --git a/string.c b/string.c index a2287b8f28..8782e41bc2 100644 --- a/string.c +++ b/string.c @@ -1913,8 +1913,13 @@ rb_str_sub_bang(argc, argv, str) regs = RMATCH(match)->regs; if (iter) { + char *p = RSTRING(str)->ptr; long len = RSTRING(str)->len; + rb_match_busy(match); repl = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match))); + if (RSTRING(str)->ptr != p || RSTRING(str)->len != len) { + rb_raise(rb_eRuntimeError, "string modified"); + } rb_backref_set(match); } else { @@ -3095,7 +3100,7 @@ tr_setup_table(str, table, init) buf[c & 0xff] = !cflag; } for (i=0; i<256; i++) { - table[i] = table[i]&&buf[i]; + table[i] = table[i] && buf[i]; } } @@ -3554,6 +3559,17 @@ rb_f_split(argc, argv) } +static inline void +str_mod_check(s, p, len) + VALUE s; + char *p; + long len; +{ + if (RSTRING(s)->ptr != p || RSTRING(s)->len != len) { + rb_raise(rb_eRuntimeError, "string modified"); + } +} + /* * call-seq: * str.each(separator=$/) {|substr| block } => str @@ -3628,8 +3644,7 @@ rb_str_each_line(argc, argv, str) line = rb_str_new5(str, s, p - s); OBJ_INFECT(line, str); rb_yield(line); - if (RSTRING(str)->ptr != ptr || RSTRING(str)->len != len) - rb_raise(rb_eArgError, "string modified"); + str_mod_check(str, ptr, len); s = p; } } @@ -3799,11 +3814,13 @@ rb_str_chomp_bang(argc, argv, str) { VALUE rs; int newline; - char *p = RSTRING(str)->ptr; - long len = RSTRING(str)->len, rslen; + char *p; + long len, rslen; if (rb_scan_args(argc, argv, "01", &rs) == 0) { + len = RSTRING(str)->len; if (len == 0) return Qnil; + p = RSTRING(str)->ptr; rs = rb_rs; if (rs == rb_default_rs) { smart_chomp: @@ -3827,9 +3844,10 @@ rb_str_chomp_bang(argc, argv, str) } } if (NIL_P(rs)) return Qnil; - if (len == 0) return Qnil; - StringValue(rs); + len = RSTRING(str)->len; + if (len == 0) return Qnil; + p = RSTRING(str)->ptr; rslen = RSTRING(rs)->len; if (rslen == 0) { while (len>0 && p[len-1] == '\n') { @@ -4277,7 +4295,7 @@ rb_str_crypt(str, salt) { extern char *crypt(); VALUE result; - char *s; + char *s, *cr; StringValue(salt); if (RSTRING(salt)->len < 2) @@ -4285,7 +4303,10 @@ rb_str_crypt(str, salt) if (RSTRING(str)->ptr) s = RSTRING(str)->ptr; else s = ""; - result = rb_str_new2(crypt(s, RSTRING(salt)->ptr)); + cr = crypt(s, RSTRING(salt)->ptr); + s = ALLOCA_N(char, strlen(cr)); + strcpy(s, cr); + result = rb_str_new2(s); OBJ_INFECT(result, str); OBJ_INFECT(result, salt); return result; @@ -4348,14 +4369,17 @@ rb_str_sum(argc, argv, str) { VALUE vbits; int bits; - char *p, *pend; + char *ptr, *p, *pend; + long len; if (rb_scan_args(argc, argv, "01", &vbits) == 0) { bits = 16; } else bits = NUM2INT(vbits); - p = RSTRING(str)->ptr; pend = p + RSTRING(str)->len; + ptr = p = RSTRING(str)->ptr; + len = RSTRING(str)->len; + pend = p + len; if (bits > sizeof(long)*CHAR_BIT) { VALUE res = INT2FIX(0); VALUE mod; @@ -4364,6 +4388,7 @@ rb_str_sum(argc, argv, str) mod = rb_funcall(mod, '-', 1, INT2FIX(1)); while (p < pend) { + str_mod_check(str, ptr, len); res = rb_funcall(res, '+', 1, INT2FIX((unsigned int)*p)); p++; } @@ -4378,6 +4403,7 @@ rb_str_sum(argc, argv, str) mod = -1; } while (p < pend) { + str_mod_check(str, ptr, len); res += (unsigned int)*p; p++; } diff --git a/struct.c b/struct.c index 4fab88fc0f..b5454b4bea 100644 --- a/struct.c +++ b/struct.c @@ -34,18 +34,43 @@ rb_struct_iv_get(c, name) } static VALUE -rb_struct_s_members(obj) - VALUE obj; +struct_s_members(klass) + VALUE klass; { - VALUE member, ary; - VALUE *p, *pend; + VALUE members = rb_struct_iv_get(klass, "__members__"); - member = rb_struct_iv_get(obj, "__member__"); - if (NIL_P(member)) { - rb_bug("uninitialized struct"); + if (NIL_P(members)) { + rb_bug("non-initialized struct"); } - ary = rb_ary_new2(RARRAY(member)->len); - p = RARRAY(member)->ptr; pend = p + RARRAY(member)->len; + return members; +} + +static VALUE +struct_members(s) + VALUE s; +{ + VALUE members = struct_s_members(rb_obj_class(s)); + + if (NIL_P(members)) { + rb_bug("non-initialized struct"); + } + if (RSTRUCT(s)->len != RARRAY(members)->len) { + rb_raise(rb_eTypeError, "struct size differs (%d required %d given)", + RARRAY(members)->len, RSTRUCT(s)->len); + } + return members; +} + +static VALUE +rb_struct_s_members(klass) + VALUE klass; +{ + VALUE members, ary; + VALUE *p, *pend; + + members = struct_s_members(klass); + ary = rb_ary_new2(RARRAY(members)->len); + p = RARRAY(members)->ptr; pend = p + RARRAY(members)->len; while (p < pend) { rb_ary_push(ary, rb_str_new2(rb_id2name(SYM2ID(*p)))); p++; @@ -78,16 +103,16 @@ rb_struct_getmember(obj, id) VALUE obj; ID id; { - VALUE member, slot; + VALUE members, slot; long i; - member = rb_struct_iv_get(rb_obj_class(obj), "__member__"); - if (NIL_P(member)) { + members = rb_struct_iv_get(rb_obj_class(obj), "__members__"); + if (NIL_P(members)) { rb_bug("uninitialized struct"); } slot = ID2SYM(id); - for (i=0; ilen; i++) { - if (RARRAY(member)->ptr[i] == slot) { + for (i=0; ilen; i++) { + if (RARRAY(members)->ptr[i] == slot) { return RSTRUCT(obj)->ptr[i]; } } @@ -139,16 +164,16 @@ static VALUE rb_struct_set(obj, val) VALUE obj, val; { - VALUE member, slot; + VALUE members, slot; long i; - member = rb_struct_iv_get(rb_obj_class(obj), "__member__"); - if (NIL_P(member)) { + members = rb_struct_iv_get(rb_obj_class(obj), "__members__"); + if (NIL_P(members)) { rb_bug("uninitialized struct"); } rb_struct_modify(obj); - for (i=0; ilen; i++) { - slot = RARRAY(member)->ptr[i]; + for (i=0; ilen; i++) { + slot = RARRAY(members)->ptr[i]; if (rb_id_attrset(SYM2ID(slot)) == rb_frame_last_func()) { return RSTRUCT(obj)->ptr[i] = val; } @@ -159,13 +184,14 @@ rb_struct_set(obj, val) } static VALUE -make_struct(name, member, klass) - VALUE name, member, klass; +make_struct(name, members, klass) + VALUE name, members, klass; { VALUE nstr; ID id; long i; + OBJ_FREEZE(members); if (NIL_P(name)) { nstr = rb_class_new(klass); rb_make_metaclass(nstr, RBASIC(klass)->klass); @@ -183,15 +209,15 @@ make_struct(name, member, klass) } nstr = rb_define_class_under(klass, cname, klass); } - rb_iv_set(nstr, "__size__", LONG2NUM(RARRAY(member)->len)); - rb_iv_set(nstr, "__member__", member); + rb_iv_set(nstr, "__size__", LONG2NUM(RARRAY(members)->len)); + rb_iv_set(nstr, "__members__", members); rb_define_alloc_func(nstr, struct_alloc); rb_define_singleton_method(nstr, "new", rb_class_new_instance, -1); rb_define_singleton_method(nstr, "[]", rb_class_new_instance, -1); rb_define_singleton_method(nstr, "members", rb_struct_s_members, 0); - for (i=0; i< RARRAY(member)->len; i++) { - ID id = SYM2ID(RARRAY(member)->ptr[i]); + for (i=0; i< RARRAY(members)->len; i++) { + ID id = SYM2ID(RARRAY(members)->ptr[i]); if (i<10) { rb_define_method_id(nstr, id, ref_func[i], 0); } @@ -427,15 +453,12 @@ static VALUE rb_struct_each_pair(s) VALUE s; { - VALUE member; + VALUE members; long i; - member = rb_struct_iv_get(rb_obj_class(s), "__member__"); - if (NIL_P(member)) { - rb_bug("non-initialized struct"); - } + members = struct_members(s); for (i=0; ilen; i++) { - rb_yield_values(2, RARRAY(member)->ptr[i], RSTRUCT(s)->ptr[i]); + rb_yield_values(2, rb_ary_entry(members, i), RSTRUCT(s)->ptr[i]); } return s; } @@ -445,14 +468,10 @@ inspect_struct(s) VALUE s; { char *cname = rb_class2name(rb_obj_class(s)); - VALUE str, member; + VALUE str, members; long i; - member = rb_struct_iv_get(rb_obj_class(s), "__member__"); - if (NIL_P(member)) { - rb_bug("non-initialized struct"); - } - + members = struct_members(s); str = rb_str_buf_new2("# 0) { rb_str_cat2(str, ", "); } - slot = RARRAY(member)->ptr[i]; + slot = RARRAY(members)->ptr[i]; p = rb_id2name(SYM2ID(slot)); rb_str_cat2(str, p); rb_str_cat2(str, "="); @@ -539,17 +558,13 @@ rb_struct_aref_id(s, id) VALUE s; ID id; { - VALUE member; + VALUE members; long i, len; - member = rb_struct_iv_get(rb_obj_class(s), "__member__"); - if (NIL_P(member)) { - rb_bug("non-initialized struct"); - } - - len = RARRAY(member)->len; + members = struct_members(s); + len = RARRAY(members)->len; for (i=0; iptr[i]) == id) { + if (SYM2ID(RARRAY(members)->ptr[i]) == id) { return RSTRUCT(s)->ptr[i]; } } @@ -602,18 +617,18 @@ rb_struct_aset_id(s, id, val) VALUE s, val; ID id; { - VALUE member; + VALUE members; long i, len; - member = rb_struct_iv_get(rb_obj_class(s), "__member__"); - if (NIL_P(member)) { - rb_bug("non-initialized struct"); - } - + members = struct_members(s); rb_struct_modify(s); - len = RARRAY(member)->len; + len = RARRAY(members)->len; + if (RSTRUCT(s)->len != RARRAY(members)->len) { + rb_raise(rb_eTypeError, "struct size differs (%d required %d given)", + RARRAY(members)->len, RSTRUCT(s)->len); + } for (i=0; iptr[i]) == id) { + if (SYM2ID(RARRAY(members)->ptr[i]) == id) { RSTRUCT(s)->ptr[i] = val; return val; } diff --git a/variable.c b/variable.c index e97eef0f7a..78445994c2 100644 --- a/variable.c +++ b/variable.c @@ -98,7 +98,7 @@ fc_i(key, value, res) arg.klass = res->klass; arg.track = value; arg.prev = res; - st_foreach(RCLASS(value)->iv_tbl, fc_i, (st_data_t)&arg); + st_foreach_safe(RCLASS(value)->iv_tbl, fc_i, (st_data_t)&arg); if (arg.path) { res->path = arg.path; return ST_STOP; @@ -124,7 +124,7 @@ find_class_path(klass) arg.track = rb_cObject; arg.prev = 0; if (RCLASS(rb_cObject)->iv_tbl) { - st_foreach(RCLASS(rb_cObject)->iv_tbl, fc_i, (st_data_t)&arg); + st_foreach_safe(RCLASS(rb_cObject)->iv_tbl, fc_i, (st_data_t)&arg); } if (arg.path == 0) { st_foreach(rb_class_tbl, fc_i, (st_data_t)&arg); @@ -958,7 +958,7 @@ rb_mark_generic_ivar_tbl() { if (!generic_iv_tbl) return; if (special_generic_ivar == 0) return; - st_foreach(generic_iv_tbl, givar_i, 0); + st_foreach_safe(generic_iv_tbl, givar_i, 0); } void @@ -1118,7 +1118,7 @@ rb_obj_instance_variables(obj) case T_CLASS: case T_MODULE: if (ROBJECT(obj)->iv_tbl) { - st_foreach(ROBJECT(obj)->iv_tbl, ivar_i, ary); + st_foreach_safe(ROBJECT(obj)->iv_tbl, ivar_i, ary); } break; default: @@ -1127,7 +1127,7 @@ rb_obj_instance_variables(obj) st_table *tbl; if (st_lookup(generic_iv_tbl, obj, (st_data_t *)&tbl)) { - st_foreach(tbl, ivar_i, ary); + st_foreach_safe(tbl, ivar_i, ary); } } break; @@ -1511,7 +1511,7 @@ rb_mod_const_at(mod, data) tbl = st_init_numtable(); } if (RCLASS(mod)->iv_tbl) { - st_foreach(RCLASS(mod)->iv_tbl, sv_i, (st_data_t)tbl); + st_foreach_safe(RCLASS(mod)->iv_tbl, sv_i, (st_data_t)tbl); } return tbl; } @@ -1875,7 +1875,7 @@ rb_mod_class_variables(obj) for (;;) { if (RCLASS(obj)->iv_tbl) { - st_foreach(RCLASS(obj)->iv_tbl, cv_i, ary); + st_foreach_safe(RCLASS(obj)->iv_tbl, cv_i, ary); } obj = RCLASS(obj)->super; if (!obj) break; -- cgit v1.2.3