summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-10-02 03:50:53 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-10-02 03:50:53 +0000
commit6f9dcadf6e46c80bb1f807f88a691cfe388f4f8b (patch)
tree5756b304650334db0189529589f40dcd4beae38c
parentd57bbd48f8d43b512d171f53edc198d3043d933c (diff)
* 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
-rw-r--r--ChangeLog57
-rw-r--r--array.c57
-rw-r--r--enum.c25
-rw-r--r--eval.c15
-rw-r--r--ext/socket/socket.c2
-rw-r--r--file.c11
-rw-r--r--hash.c116
-rw-r--r--intern.h2
-rw-r--r--io.c6
-rw-r--r--marshal.c4
-rw-r--r--object.c2
-rw-r--r--process.c2
-rw-r--r--re.c4
-rw-r--r--string.c48
-rw-r--r--struct.c123
-rw-r--r--variable.c14
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 <matz@ruby-lang.org>
+
+ * 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 <matz@ruby-lang.org>
+
+ * 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 <nagai@ai.kyutech.ac.jp>
* ext/tk/lib/tk/grid.rb: revive TkGrid.grid
@@ -22,6 +49,36 @@ Wed Sep 29 10:58:07 2004 Nobuyoshi Nakada <nobu@ruby-lang.org>
* 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 <matz@ruby-lang.org>
+
+ * ext/socket/socket.c (s_accept): don't retry for EWOULDBLOCK.
+ [ruby-talk:113807]
+
+Fri Sep 24 16:09:42 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * 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 <matz@ruby-lang.org>
+
+ * 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 <matz@ruby-lang.org>
+
+ * 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 <matz@ruby-lang.org>
* 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 (i<RARRAY(ary)->len) {
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; i<RARRAY(ary)->len; 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; i<RARRAY(keys)->len; 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; i<RARRAY(member)->len; i++) {
- if (RARRAY(member)->ptr[i] == slot) {
+ for (i=0; i<RARRAY(members)->len; 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; i<RARRAY(member)->len; i++) {
- slot = RARRAY(member)->ptr[i];
+ for (i=0; i<RARRAY(members)->len; 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; i<RSTRUCT(s)->len; 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("#<struct ");
rb_str_cat2(str, cname);
rb_str_cat2(str, " ");
@@ -463,7 +482,7 @@ inspect_struct(s)
if (i > 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; i<len; i++) {
- if (SYM2ID(RARRAY(member)->ptr[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; i<len; i++) {
- if (SYM2ID(RARRAY(member)->ptr[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;