1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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
This commit is contained in:
matz 2004-10-02 03:50:53 +00:00
parent d57bbd48f8
commit 6f9dcadf6e
16 changed files with 328 additions and 160 deletions

View file

@ -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> Fri Oct 1 11:25:20 2004 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
* ext/tk/lib/tk/grid.rb: revive TkGrid.grid * 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 * enum.c (sort_by_i): internally used object must not be changed
outside. [ruby-dev:24368] 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> Wed Sep 22 13:38:12 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
* hash.c (rb_hash_rehash): add iteration check. [ruby-dev:24301] * hash.c (rb_hash_rehash): add iteration check. [ruby-dev:24301]

57
array.c
View file

@ -459,7 +459,7 @@ rb_ary_pop(ary)
return RARRAY(ary)->ptr[--RARRAY(ary)->len]; return RARRAY(ary)->ptr[--RARRAY(ary)->len];
} }
static void static VALUE
ary_make_shared(ary) ary_make_shared(ary)
VALUE ary; VALUE ary;
{ {
@ -472,6 +472,11 @@ ary_make_shared(ary)
shared->aux.capa = RARRAY(ary)->aux.capa; shared->aux.capa = RARRAY(ary)->aux.capa;
RARRAY(ary)->aux.shared = (VALUE)shared; RARRAY(ary)->aux.shared = (VALUE)shared;
FL_SET(ary, ELTS_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; VALUE ary;
long beg, len; long beg, len;
{ {
VALUE klass, ary2; VALUE klass, ary2, shared;
VALUE *ptr;
if (beg > RARRAY(ary)->len) return Qnil; if (beg > RARRAY(ary)->len) return Qnil;
if (beg < 0 || len < 0) return Qnil; if (beg < 0 || len < 0) return Qnil;
@ -604,11 +610,12 @@ rb_ary_subseq(ary, beg, len)
klass = rb_obj_class(ary); klass = rb_obj_class(ary);
if (len == 0) return ary_new(klass, 0); 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); ary2 = ary_alloc(klass);
RARRAY(ary2)->ptr = RARRAY(ary)->ptr + beg; RARRAY(ary2)->ptr = ptr + beg;
RARRAY(ary2)->len = len; RARRAY(ary2)->len = len;
RARRAY(ary2)->aux.shared = RARRAY(ary)->aux.shared; RARRAY(ary2)->aux.shared = shared;
FL_SET(ary2, ELTS_SHARED); FL_SET(ary2, ELTS_SHARED);
return ary2; return ary2;
@ -1562,9 +1569,10 @@ sort_1(a, b, data)
struct ary_sort_data *data; struct ary_sort_data *data;
{ {
VALUE retval = rb_yield_values(2, *a, *b); VALUE retval = rb_yield_values(2, *a, *b);
int n;
ary_sort_check(data); n = rb_cmpint(retval, *a, *b);
return rb_cmpint(retval, *a, *b); return n;
} }
static int static int
@ -1573,11 +1581,12 @@ sort_2(ap, bp, data)
struct ary_sort_data *data; struct ary_sort_data *data;
{ {
VALUE retval; VALUE retval;
long a = (long)*ap, b = (long)*bp; VALUE a = *ap, b = *bp;
int n;
if (FIXNUM_P(a) && FIXNUM_P(b)) { if (FIXNUM_P(a) && FIXNUM_P(b)) {
if (a > b) return 1; if ((long)a > (long)b) return 1;
if (a < b) return -1; if ((long)a < (long)b) return -1;
return 0; return 0;
} }
if (TYPE(a) == T_STRING && TYPE(b) == T_STRING) { 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); retval = rb_funcall(a, id_cmp, 1, b);
ary_sort_check(data); n = rb_cmpint(retval, a, b);
return rb_cmpint(retval, a, b);
return n;
} }
static VALUE static VALUE
@ -2150,15 +2160,17 @@ static VALUE
rb_ary_replace(copy, orig) rb_ary_replace(copy, orig)
VALUE copy, orig; VALUE copy, orig;
{ {
VALUE shared;
rb_ary_modify(copy); rb_ary_modify(copy);
orig = to_ary(orig); orig = to_ary(orig);
if (copy == orig) return copy; if (copy == orig) return copy;
ary_make_shared(orig); shared = ary_make_shared(orig);
if (RARRAY(copy)->ptr && !FL_TEST(copy, ELTS_SHARED)) if (RARRAY(copy)->ptr && !FL_TEST(copy, ELTS_SHARED))
free(RARRAY(copy)->ptr); free(RARRAY(copy)->ptr);
RARRAY(copy)->ptr = RARRAY(orig)->ptr; RARRAY(copy)->ptr = RARRAY(shared)->ptr;
RARRAY(copy)->len = RARRAY(orig)->len; RARRAY(copy)->len = RARRAY(shared)->len;
RARRAY(copy)->aux.shared = RARRAY(orig)->aux.shared; RARRAY(copy)->aux.shared = shared;
FL_SET(copy, ELTS_SHARED); FL_SET(copy, ELTS_SHARED);
return copy; return copy;
@ -2874,8 +2886,11 @@ flatten(ary, idx, ary2, memo)
rb_ary_push(memo, id); rb_ary_push(memo, id);
rb_ary_update(ary, idx, 1, ary2); rb_ary_update(ary, idx, 1, ary2);
while (i < lim) { while (i < lim) {
if (TYPE(RARRAY(ary)->ptr[i]) == T_ARRAY) { VALUE tmp;
n = flatten(ary, i, RARRAY(ary)->ptr[i], memo);
tmp = rb_check_array_type(RARRAY(ary)->ptr[i]);
if (!NIL_P(tmp)) {
n = flatten(ary, i, tmp, memo);
i += n; lim += n; i += n; lim += n;
} }
i++; i++;
@ -2910,12 +2925,14 @@ rb_ary_flatten_bang(ary)
rb_ary_modify(ary); rb_ary_modify(ary);
while (i<RARRAY(ary)->len) { while (i<RARRAY(ary)->len) {
VALUE ary2 = RARRAY(ary)->ptr[i]; 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)) { if (NIL_P(memo)) {
memo = rb_ary_new(); memo = rb_ary_new();
} }
i += flatten(ary, i, ary2, memo); i += flatten(ary, i, tmp, memo);
mod = 1; mod = 1;
} }
i++; i++;

25
enum.c
View file

@ -389,26 +389,26 @@ static VALUE
sort_by_i(i, ary) sort_by_i(i, ary)
VALUE i, ary; VALUE i, ary;
{ {
VALUE v, e; VALUE v;
NODE *memo;
v = rb_yield(i); v = rb_yield(i);
e = rb_assoc_new(v, i); memo = rb_node_newnode(NODE_MEMO, v, i, 0);
OBJ_FREEZE(e); rb_ary_push(ary, (VALUE)memo);
rb_ary_push(ary, e);
return Qnil; return Qnil;
} }
static VALUE static VALUE
sort_by_cmp(values, ary) sort_by_cmp(values, ary)
VALUE values; VALUE values, ary;
{ {
VALUE a = RARRAY(values)->ptr[0]; NODE *a = (NODE*)RARRAY(values)->ptr[0];
VALUE b = RARRAY(values)->ptr[1]; NODE *b = (NODE*)RARRAY(values)->ptr[1];
/* pedantic check; they must be arrays */ /* pedantic check; they must be memo nodes */
Check_Type(a, T_ARRAY); Check_Type(a, T_NODE);
Check_Type(b, T_ARRAY); Check_Type(b, T_NODE);
return rb_funcall(RARRAY(a)->ptr[0], id_cmp, 1, RARRAY(b)->ptr[0]); 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); rb_iterate(rb_ary_sort_bang, ary, sort_by_cmp, ary);
} }
for (i=0; i<RARRAY(ary)->len; i++) { for (i=0; i<RARRAY(ary)->len; i++) {
VALUE e = RARRAY(ary)->ptr[i]; RARRAY(ary)->ptr[i] = RNODE(RARRAY(ary)->ptr[i])->u2.value;
RARRAY(ary)->ptr[i] = RARRAY(e)->ptr[1];
} }
return ary; return ary;
} }

15
eval.c
View file

@ -6187,12 +6187,13 @@ rb_f_eval(argc, argv, self)
SafeStringValue(src); SafeStringValue(src);
} }
if (argc >= 3) { if (argc >= 3) {
file = StringValuePtr(vfile); StringValue(vfile);
} }
if (argc >= 4) { if (argc >= 4) {
line = NUM2INT(vline); line = NUM2INT(vline);
} }
if (!NIL_P(vfile)) file = RSTRING(vfile)->ptr;
if (NIL_P(scope) && ruby_frame->prev) { if (NIL_P(scope) && ruby_frame->prev) {
struct FRAME *prev; struct FRAME *prev;
VALUE val; VALUE val;
@ -8096,6 +8097,14 @@ proc_invoke(proc, args, self, klass)
POP_ITER(); POP_ITER();
ruby_block = old_block; ruby_block = old_block;
ruby_wrapper = old_wrapper; 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_dyna_vars = old_dvars;
ruby_safe_level = safe; ruby_safe_level = safe;
@ -12076,6 +12085,7 @@ rb_callcc(self)
volatile rb_thread_t th_save; volatile rb_thread_t th_save;
struct tag *tag; struct tag *tag;
struct RVarmap *vars; struct RVarmap *vars;
struct BLOCK *blk;
THREAD_ALLOC(th); THREAD_ALLOC(th);
cont = Data_Wrap_Struct(rb_cCont, thread_mark, thread_free, th); cont = Data_Wrap_Struct(rb_cCont, thread_mark, thread_free, th);
@ -12086,11 +12096,10 @@ rb_callcc(self)
} }
th->thread = curr_thread->thread; 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; if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
FL_SET(vars, DVAR_DONT_RECYCLE); FL_SET(vars, DVAR_DONT_RECYCLE);
} }
th_save = th; th_save = th;
if (THREAD_SAVE_CONTEXT(th)) { if (THREAD_SAVE_CONTEXT(th)) {
return th_save->result; return th_save->result;

View file

@ -1168,6 +1168,8 @@ s_accept(klass, fd, sockaddr, len)
rb_gc(); rb_gc();
retry = 1; retry = 1;
goto retry; goto retry;
case EWOULDBLOCK:
break;
default: default:
if (!rb_io_wait_readable(fd)) break; if (!rb_io_wait_readable(fd)) break;
retry = 0; retry = 0;

11
file.c
View file

@ -1644,8 +1644,7 @@ rb_file_s_lchmod(argc, argv)
{ {
VALUE vmode; VALUE vmode;
VALUE rest; VALUE rest;
int mode; long mode, n;
long n;
rb_secure(2); rb_secure(2);
rb_scan_args(argc, argv, "1*", &vmode, &rest); rb_scan_args(argc, argv, "1*", &vmode, &rest);
@ -2560,11 +2559,11 @@ rb_file_s_basename(argc, argv)
VALUE *argv; VALUE *argv;
{ {
VALUE fname, fext, basename; VALUE fname, fext, basename;
char *name, *p, *ext = NULL; char *name, *p;
int f; int f;
if (rb_scan_args(argc, argv, "11", &fname, &fext) == 2) { if (rb_scan_args(argc, argv, "11", &fname, &fext) == 2) {
ext = StringValueCStr(fext); StringValue(fext);
} }
StringValue(fname); StringValue(fname);
if (RSTRING(fname)->len == 0 || !*(name = RSTRING(fname)->ptr)) if (RSTRING(fname)->len == 0 || !*(name = RSTRING(fname)->ptr))
@ -2580,7 +2579,7 @@ rb_file_s_basename(argc, argv)
#endif #endif
} }
else if (!(p = strrdirsep(name))) { 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; f = chompdirsep(name) - name;
if (f == RSTRING(fname)->len) return fname; if (f == RSTRING(fname)->len) return fname;
} }
@ -2588,7 +2587,7 @@ rb_file_s_basename(argc, argv)
} }
else { else {
while (isdirsep(*p)) p++; /* skip last / */ 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; f = chompdirsep(p) - p;
} }
} }

116
hash.c
View file

@ -114,16 +114,54 @@ static struct st_hash_type objhash = {
rb_any_hash, 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; VALUE hash;
enum st_retval (*func)(); int (*func)();
VALUE arg; VALUE arg;
}; };
static int static int
rb_hash_foreach_iter(key, value, arg, err) hash_foreach_iter(key, value, arg, err)
VALUE key, value; VALUE key, value;
struct rb_hash_foreach_arg *arg; struct hash_foreach_arg *arg;
int err; int err;
{ {
int status; int status;
@ -151,15 +189,7 @@ rb_hash_foreach_iter(key, value, arg, err)
} }
static VALUE static VALUE
rb_hash_foreach_call(arg) hash_foreach_ensure(hash)
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)
VALUE hash; VALUE hash;
{ {
RHASH(hash)->iter_lev--; RHASH(hash)->iter_lev--;
@ -173,19 +203,27 @@ rb_hash_foreach_ensure(hash)
return 0; 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) rb_hash_foreach(hash, func, farg)
VALUE hash; VALUE hash;
enum st_retval (*func)(); int (*func)();
VALUE farg; VALUE farg;
{ {
struct rb_hash_foreach_arg arg; struct hash_foreach_arg arg;
RHASH(hash)->iter_lev++; RHASH(hash)->iter_lev++;
arg.hash = hash; arg.hash = hash;
arg.func = func; arg.func = func;
arg.arg = farg; 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)); static VALUE hash_alloc _((VALUE));
@ -354,7 +392,7 @@ rb_hash_rehash(hash)
rb_hash_modify(hash); rb_hash_modify(hash);
tbl = st_init_table_with_size(&objhash, RHASH(hash)->tbl->num_entries); 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); st_free_table(RHASH(hash)->tbl);
RHASH(hash)->tbl = tbl; RHASH(hash)->tbl = tbl;
@ -566,7 +604,7 @@ rb_hash_index(hash, value)
args[0] = value; args[0] = value;
args[1] = Qnil; 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]; return args[1];
} }
@ -678,7 +716,7 @@ rb_hash_shift(hash)
rb_hash_modify(hash); rb_hash_modify(hash);
var.stop = 0; 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) { if (var.stop) {
return rb_assoc_new(var.key, var.val); 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) delete_if_i(key, value, hash)
VALUE key, value, hash; VALUE key, value, hash;
{ {
@ -758,7 +796,7 @@ rb_hash_reject(hash)
return rb_hash_delete_if(rb_obj_dup(hash)); return rb_hash_delete_if(rb_obj_dup(hash));
} }
static enum st_retval static int
select_i(key, value, result) select_i(key, value, result)
VALUE key, value, result; VALUE key, value, result;
{ {
@ -849,7 +887,7 @@ rb_hash_clear(hash)
rb_hash_modify(hash); rb_hash_modify(hash);
if (RHASH(hash)->tbl->num_entries > 0) { if (RHASH(hash)->tbl->num_entries > 0) {
st_foreach(RHASH(hash)->tbl, clear_i, 0); rb_hash_foreach(hash, clear_i, 0);
} }
return hash; return hash;
@ -917,7 +955,7 @@ rb_hash_replace(hash, hash2)
hash2 = to_hash(hash2); hash2 = to_hash(hash2);
if (hash == hash2) return hash; if (hash == hash2) return hash;
rb_hash_clear(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; RHASH(hash)->ifnone = RHASH(hash2)->ifnone;
if (FL_TEST(hash2, HASH_PROC_DEFAULT)) { if (FL_TEST(hash2, HASH_PROC_DEFAULT)) {
FL_SET(hash, HASH_PROC_DEFAULT); FL_SET(hash, HASH_PROC_DEFAULT);
@ -969,7 +1007,7 @@ rb_hash_empty_p(hash)
return Qfalse; return Qfalse;
} }
static enum st_retval static int
each_value_i(key, value) each_value_i(key, value)
VALUE key, value; VALUE key, value;
{ {
@ -1002,7 +1040,7 @@ rb_hash_each_value(hash)
return hash; return hash;
} }
static enum st_retval static int
each_key_i(key, value) each_key_i(key, value)
VALUE key, value; VALUE key, value;
{ {
@ -1034,7 +1072,7 @@ rb_hash_each_key(hash)
return hash; return hash;
} }
static enum st_retval static int
each_pair_i(key, value) each_pair_i(key, value)
VALUE key, value; VALUE key, value;
{ {
@ -1068,7 +1106,7 @@ rb_hash_each_pair(hash)
return hash; return hash;
} }
static enum st_retval static int
each_i(key, value) each_i(key, value)
VALUE key, value; VALUE key, value;
{ {
@ -1132,7 +1170,7 @@ rb_hash_to_a(hash)
VALUE ary; VALUE ary;
ary = rb_ary_new(); 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); if (OBJ_TAINTED(hash)) OBJ_TAINT(ary);
return ary; return ary;
@ -1190,7 +1228,7 @@ inspect_hash(hash)
VALUE str; VALUE str;
str = rb_str_buf_new2("{"); 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, "}"); rb_str_buf_cat2(str, "}");
OBJ_INFECT(str, hash); OBJ_INFECT(str, hash);
@ -1284,7 +1322,7 @@ rb_hash_keys(hash)
VALUE ary; VALUE ary;
ary = rb_ary_new(); ary = rb_ary_new();
st_foreach(RHASH(hash)->tbl, keys_i, ary); rb_hash_foreach(hash, keys_i, ary);
return ary; return ary;
} }
@ -1317,7 +1355,7 @@ rb_hash_values(hash)
VALUE ary; VALUE ary;
ary = rb_ary_new(); ary = rb_ary_new();
st_foreach(RHASH(hash)->tbl, values_i, ary); rb_hash_foreach(hash, values_i, ary);
return ary; return ary;
} }
@ -1382,7 +1420,7 @@ rb_hash_has_value(hash, val)
data[0] = Qfalse; data[0] = Qfalse;
data[1] = val; 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]; return data[0];
} }
@ -1434,7 +1472,7 @@ hash_equal(hash1, hash2, eql)
data.tbl = RHASH(hash2)->tbl; data.tbl = RHASH(hash2)->tbl;
data.result = Qtrue; 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; return data.result;
} }
@ -1509,7 +1547,7 @@ rb_hash_invert(hash)
{ {
VALUE h = rb_hash_new(); 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; return h;
} }
@ -1555,10 +1593,10 @@ rb_hash_update(hash1, hash2)
{ {
hash2 = to_hash(hash2); hash2 = to_hash(hash2);
if (rb_block_given_p()) { 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 { else {
st_foreach(RHASH(hash2)->tbl, rb_hash_update_i, hash1); rb_hash_foreach(hash2, rb_hash_update_i, hash1);
} }
return hash1; return hash1;
} }
@ -2345,7 +2383,7 @@ env_replace(env, hash)
if (env == hash) return env; if (env == hash) return env;
hash = to_hash(hash); 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++) { for (i=0; i<RARRAY(keys)->len; i++) {
env_delete(env, RARRAY(keys)->ptr[i]); env_delete(env, RARRAY(keys)->ptr[i]);
@ -2372,7 +2410,7 @@ env_update(env, hash)
{ {
if (env == hash) return env; if (env == hash) return env;
hash = to_hash(hash); hash = to_hash(hash);
st_foreach(RHASH(hash)->tbl, env_update_i, 0); rb_hash_foreach(hash, env_update_i, 0);
return env; return env;
} }

View file

@ -245,6 +245,8 @@ VALUE rb_gc_enable _((void));
VALUE rb_gc_disable _((void)); VALUE rb_gc_disable _((void));
VALUE rb_gc_start _((void)); VALUE rb_gc_start _((void));
/* hash.c */ /* 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 _((VALUE));
VALUE rb_hash_new _((void)); VALUE rb_hash_new _((void));
VALUE rb_hash_freeze _((VALUE)); VALUE rb_hash_freeze _((VALUE));

6
io.c
View file

@ -1067,11 +1067,13 @@ io_read(argc, argv, io)
StringValue(str); StringValue(str);
rb_str_modify(str); rb_str_modify(str);
rb_str_resize(str,len); rb_str_resize(str,len);
FL_SET(str, FL_FREEZE);
} }
if (len == 0) return str; if (len == 0) return str;
READ_CHECK(fptr->f); READ_CHECK(fptr->f);
n = rb_io_fread(RSTRING(str)->ptr, len, fptr->f); n = rb_io_fread(RSTRING(str)->ptr, len, fptr->f);
FL_UNSET(str, FL_FREEZE);
if (n == 0) { if (n == 0) {
rb_str_resize(str,0); rb_str_resize(str,0);
if (!fptr->f) return Qnil; if (!fptr->f) return Qnil;
@ -2721,7 +2723,9 @@ rb_io_popen(str, argc, argv, klass)
mode = rb_io_modenum_mode(FIX2INT(pmode), mbuf); mode = rb_io_modenum_mode(FIX2INT(pmode), mbuf);
} }
else { else {
mode = StringValuePtr(pmode); strncpy(mbuf, StringValuePtr(pmode), sizeof(mbuf) - 1);
mbuf[sizeof(mbuf) - 1] = 0;
mode = mbuf;
} }
SafeStringValue(pname); SafeStringValue(pname);
port = pipe_open(str, mode); port = pipe_open(str, mode);

View file

@ -437,7 +437,7 @@ w_ivar(tbl, arg)
{ {
if (tbl) { if (tbl) {
w_long(tbl->num_entries, arg->arg); 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 { else {
w_long(0, arg->arg); w_long(0, arg->arg);
@ -621,7 +621,7 @@ w_object(obj, arg, limit)
w_byte(TYPE_HASH_DEF, arg); w_byte(TYPE_HASH_DEF, arg);
} }
w_long(RHASH(obj)->tbl->num_entries, 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)) { if (!NIL_P(RHASH(obj)->ifnone)) {
w_object(RHASH(obj)->ifnone, arg, limit); w_object(RHASH(obj)->ifnone, arg, limit);
} }

View file

@ -404,7 +404,7 @@ static VALUE
inspect_obj(obj, str) inspect_obj(obj, str)
VALUE 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, ">"); rb_str_cat2(str, ">");
RSTRING(str)->ptr[0] = '#'; RSTRING(str)->ptr[0] = '#';
OBJ_INFECT(str, obj); OBJ_INFECT(str, obj);

View file

@ -1214,8 +1214,8 @@ rb_f_exec(argc, argv)
rb_raise(rb_eArgError, "wrong first argument"); rb_raise(rb_eArgError, "wrong first argument");
} }
prog = RARRAY(tmp)->ptr[0]; prog = RARRAY(tmp)->ptr[0];
SafeStringValue(prog);
argv[0] = RARRAY(tmp)->ptr[1]; argv[0] = RARRAY(tmp)->ptr[1];
SafeStringValue(prog);
} }
if (argc == 1 && prog == 0) { if (argc == 1 && prog == 0) {
VALUE cmd = argv[0]; VALUE cmd = argv[0];

4
re.c
View file

@ -1681,8 +1681,6 @@ rb_reg_initialize_m(argc, argv, self)
len = RREGEXP(argv[0])->len; len = RREGEXP(argv[0])->len;
} }
else { else {
s = StringValuePtr(argv[0]);
len = RSTRING(argv[0])->len;
if (argc >= 2) { if (argc >= 2) {
if (FIXNUM_P(argv[1])) flags = FIX2INT(argv[1]); if (FIXNUM_P(argv[1])) flags = FIX2INT(argv[1]);
else if (RTEST(argv[1])) flags = RE_OPTION_IGNORECASE; else if (RTEST(argv[1])) flags = RE_OPTION_IGNORECASE;
@ -1708,6 +1706,8 @@ rb_reg_initialize_m(argc, argv, self)
break; break;
} }
} }
s = StringValuePtr(argv[0]);
len = RSTRING(argv[0])->len;
} }
rb_reg_initialize(self, s, len, flags); rb_reg_initialize(self, s, len, flags);
return self; return self;

View file

@ -1913,8 +1913,13 @@ rb_str_sub_bang(argc, argv, str)
regs = RMATCH(match)->regs; regs = RMATCH(match)->regs;
if (iter) { if (iter) {
char *p = RSTRING(str)->ptr; long len = RSTRING(str)->len;
rb_match_busy(match); rb_match_busy(match);
repl = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, 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); rb_backref_set(match);
} }
else { else {
@ -3095,7 +3100,7 @@ tr_setup_table(str, table, init)
buf[c & 0xff] = !cflag; buf[c & 0xff] = !cflag;
} }
for (i=0; i<256; i++) { 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: * call-seq:
* str.each(separator=$/) {|substr| block } => str * 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); line = rb_str_new5(str, s, p - s);
OBJ_INFECT(line, str); OBJ_INFECT(line, str);
rb_yield(line); rb_yield(line);
if (RSTRING(str)->ptr != ptr || RSTRING(str)->len != len) str_mod_check(str, ptr, len);
rb_raise(rb_eArgError, "string modified");
s = p; s = p;
} }
} }
@ -3799,11 +3814,13 @@ rb_str_chomp_bang(argc, argv, str)
{ {
VALUE rs; VALUE rs;
int newline; int newline;
char *p = RSTRING(str)->ptr; char *p;
long len = RSTRING(str)->len, rslen; long len, rslen;
if (rb_scan_args(argc, argv, "01", &rs) == 0) { if (rb_scan_args(argc, argv, "01", &rs) == 0) {
len = RSTRING(str)->len;
if (len == 0) return Qnil; if (len == 0) return Qnil;
p = RSTRING(str)->ptr;
rs = rb_rs; rs = rb_rs;
if (rs == rb_default_rs) { if (rs == rb_default_rs) {
smart_chomp: smart_chomp:
@ -3827,9 +3844,10 @@ rb_str_chomp_bang(argc, argv, str)
} }
} }
if (NIL_P(rs)) return Qnil; if (NIL_P(rs)) return Qnil;
if (len == 0) return Qnil;
StringValue(rs); StringValue(rs);
len = RSTRING(str)->len;
if (len == 0) return Qnil;
p = RSTRING(str)->ptr;
rslen = RSTRING(rs)->len; rslen = RSTRING(rs)->len;
if (rslen == 0) { if (rslen == 0) {
while (len>0 && p[len-1] == '\n') { while (len>0 && p[len-1] == '\n') {
@ -4277,7 +4295,7 @@ rb_str_crypt(str, salt)
{ {
extern char *crypt(); extern char *crypt();
VALUE result; VALUE result;
char *s; char *s, *cr;
StringValue(salt); StringValue(salt);
if (RSTRING(salt)->len < 2) if (RSTRING(salt)->len < 2)
@ -4285,7 +4303,10 @@ rb_str_crypt(str, salt)
if (RSTRING(str)->ptr) s = RSTRING(str)->ptr; if (RSTRING(str)->ptr) s = RSTRING(str)->ptr;
else s = ""; 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, str);
OBJ_INFECT(result, salt); OBJ_INFECT(result, salt);
return result; return result;
@ -4348,14 +4369,17 @@ rb_str_sum(argc, argv, str)
{ {
VALUE vbits; VALUE vbits;
int bits; int bits;
char *p, *pend; char *ptr, *p, *pend;
long len;
if (rb_scan_args(argc, argv, "01", &vbits) == 0) { if (rb_scan_args(argc, argv, "01", &vbits) == 0) {
bits = 16; bits = 16;
} }
else bits = NUM2INT(vbits); 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) { if (bits > sizeof(long)*CHAR_BIT) {
VALUE res = INT2FIX(0); VALUE res = INT2FIX(0);
VALUE mod; VALUE mod;
@ -4364,6 +4388,7 @@ rb_str_sum(argc, argv, str)
mod = rb_funcall(mod, '-', 1, INT2FIX(1)); mod = rb_funcall(mod, '-', 1, INT2FIX(1));
while (p < pend) { while (p < pend) {
str_mod_check(str, ptr, len);
res = rb_funcall(res, '+', 1, INT2FIX((unsigned int)*p)); res = rb_funcall(res, '+', 1, INT2FIX((unsigned int)*p));
p++; p++;
} }
@ -4378,6 +4403,7 @@ rb_str_sum(argc, argv, str)
mod = -1; mod = -1;
} }
while (p < pend) { while (p < pend) {
str_mod_check(str, ptr, len);
res += (unsigned int)*p; res += (unsigned int)*p;
p++; p++;
} }

123
struct.c
View file

@ -34,18 +34,43 @@ rb_struct_iv_get(c, name)
} }
static VALUE static VALUE
rb_struct_s_members(obj) struct_s_members(klass)
VALUE obj; VALUE klass;
{ {
VALUE member, ary; VALUE members = rb_struct_iv_get(klass, "__members__");
if (NIL_P(members)) {
rb_bug("non-initialized struct");
}
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; VALUE *p, *pend;
member = rb_struct_iv_get(obj, "__member__"); members = struct_s_members(klass);
if (NIL_P(member)) { ary = rb_ary_new2(RARRAY(members)->len);
rb_bug("uninitialized struct"); p = RARRAY(members)->ptr; pend = p + RARRAY(members)->len;
}
ary = rb_ary_new2(RARRAY(member)->len);
p = RARRAY(member)->ptr; pend = p + RARRAY(member)->len;
while (p < pend) { while (p < pend) {
rb_ary_push(ary, rb_str_new2(rb_id2name(SYM2ID(*p)))); rb_ary_push(ary, rb_str_new2(rb_id2name(SYM2ID(*p))));
p++; p++;
@ -78,16 +103,16 @@ rb_struct_getmember(obj, id)
VALUE obj; VALUE obj;
ID id; ID id;
{ {
VALUE member, slot; VALUE members, slot;
long i; long i;
member = rb_struct_iv_get(rb_obj_class(obj), "__member__"); members = rb_struct_iv_get(rb_obj_class(obj), "__members__");
if (NIL_P(member)) { if (NIL_P(members)) {
rb_bug("uninitialized struct"); rb_bug("uninitialized struct");
} }
slot = ID2SYM(id); slot = ID2SYM(id);
for (i=0; i<RARRAY(member)->len; i++) { for (i=0; i<RARRAY(members)->len; i++) {
if (RARRAY(member)->ptr[i] == slot) { if (RARRAY(members)->ptr[i] == slot) {
return RSTRUCT(obj)->ptr[i]; return RSTRUCT(obj)->ptr[i];
} }
} }
@ -139,16 +164,16 @@ static VALUE
rb_struct_set(obj, val) rb_struct_set(obj, val)
VALUE obj, val; VALUE obj, val;
{ {
VALUE member, slot; VALUE members, slot;
long i; long i;
member = rb_struct_iv_get(rb_obj_class(obj), "__member__"); members = rb_struct_iv_get(rb_obj_class(obj), "__members__");
if (NIL_P(member)) { if (NIL_P(members)) {
rb_bug("uninitialized struct"); rb_bug("uninitialized struct");
} }
rb_struct_modify(obj); rb_struct_modify(obj);
for (i=0; i<RARRAY(member)->len; i++) { for (i=0; i<RARRAY(members)->len; i++) {
slot = RARRAY(member)->ptr[i]; slot = RARRAY(members)->ptr[i];
if (rb_id_attrset(SYM2ID(slot)) == rb_frame_last_func()) { if (rb_id_attrset(SYM2ID(slot)) == rb_frame_last_func()) {
return RSTRUCT(obj)->ptr[i] = val; return RSTRUCT(obj)->ptr[i] = val;
} }
@ -159,13 +184,14 @@ rb_struct_set(obj, val)
} }
static VALUE static VALUE
make_struct(name, member, klass) make_struct(name, members, klass)
VALUE name, member, klass; VALUE name, members, klass;
{ {
VALUE nstr; VALUE nstr;
ID id; ID id;
long i; long i;
OBJ_FREEZE(members);
if (NIL_P(name)) { if (NIL_P(name)) {
nstr = rb_class_new(klass); nstr = rb_class_new(klass);
rb_make_metaclass(nstr, RBASIC(klass)->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); nstr = rb_define_class_under(klass, cname, klass);
} }
rb_iv_set(nstr, "__size__", LONG2NUM(RARRAY(member)->len)); rb_iv_set(nstr, "__size__", LONG2NUM(RARRAY(members)->len));
rb_iv_set(nstr, "__member__", member); rb_iv_set(nstr, "__members__", members);
rb_define_alloc_func(nstr, struct_alloc); rb_define_alloc_func(nstr, struct_alloc);
rb_define_singleton_method(nstr, "new", rb_class_new_instance, -1); 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, "[]", rb_class_new_instance, -1);
rb_define_singleton_method(nstr, "members", rb_struct_s_members, 0); rb_define_singleton_method(nstr, "members", rb_struct_s_members, 0);
for (i=0; i< RARRAY(member)->len; i++) { for (i=0; i< RARRAY(members)->len; i++) {
ID id = SYM2ID(RARRAY(member)->ptr[i]); ID id = SYM2ID(RARRAY(members)->ptr[i]);
if (i<10) { if (i<10) {
rb_define_method_id(nstr, id, ref_func[i], 0); rb_define_method_id(nstr, id, ref_func[i], 0);
} }
@ -427,15 +453,12 @@ static VALUE
rb_struct_each_pair(s) rb_struct_each_pair(s)
VALUE s; VALUE s;
{ {
VALUE member; VALUE members;
long i; long i;
member = rb_struct_iv_get(rb_obj_class(s), "__member__"); members = struct_members(s);
if (NIL_P(member)) {
rb_bug("non-initialized struct");
}
for (i=0; i<RSTRUCT(s)->len; i++) { 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; return s;
} }
@ -445,14 +468,10 @@ inspect_struct(s)
VALUE s; VALUE s;
{ {
char *cname = rb_class2name(rb_obj_class(s)); char *cname = rb_class2name(rb_obj_class(s));
VALUE str, member; VALUE str, members;
long i; long i;
member = rb_struct_iv_get(rb_obj_class(s), "__member__"); members = struct_members(s);
if (NIL_P(member)) {
rb_bug("non-initialized struct");
}
str = rb_str_buf_new2("#<struct "); str = rb_str_buf_new2("#<struct ");
rb_str_cat2(str, cname); rb_str_cat2(str, cname);
rb_str_cat2(str, " "); rb_str_cat2(str, " ");
@ -463,7 +482,7 @@ inspect_struct(s)
if (i > 0) { if (i > 0) {
rb_str_cat2(str, ", "); rb_str_cat2(str, ", ");
} }
slot = RARRAY(member)->ptr[i]; slot = RARRAY(members)->ptr[i];
p = rb_id2name(SYM2ID(slot)); p = rb_id2name(SYM2ID(slot));
rb_str_cat2(str, p); rb_str_cat2(str, p);
rb_str_cat2(str, "="); rb_str_cat2(str, "=");
@ -539,17 +558,13 @@ rb_struct_aref_id(s, id)
VALUE s; VALUE s;
ID id; ID id;
{ {
VALUE member; VALUE members;
long i, len; long i, len;
member = rb_struct_iv_get(rb_obj_class(s), "__member__"); members = struct_members(s);
if (NIL_P(member)) { len = RARRAY(members)->len;
rb_bug("non-initialized struct");
}
len = RARRAY(member)->len;
for (i=0; i<len; i++) { 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]; return RSTRUCT(s)->ptr[i];
} }
} }
@ -602,18 +617,18 @@ rb_struct_aset_id(s, id, val)
VALUE s, val; VALUE s, val;
ID id; ID id;
{ {
VALUE member; VALUE members;
long i, len; long i, len;
member = rb_struct_iv_get(rb_obj_class(s), "__member__"); members = struct_members(s);
if (NIL_P(member)) {
rb_bug("non-initialized struct");
}
rb_struct_modify(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++) { 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; RSTRUCT(s)->ptr[i] = val;
return val; return val;
} }

View file

@ -98,7 +98,7 @@ fc_i(key, value, res)
arg.klass = res->klass; arg.klass = res->klass;
arg.track = value; arg.track = value;
arg.prev = res; 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) { if (arg.path) {
res->path = arg.path; res->path = arg.path;
return ST_STOP; return ST_STOP;
@ -124,7 +124,7 @@ find_class_path(klass)
arg.track = rb_cObject; arg.track = rb_cObject;
arg.prev = 0; arg.prev = 0;
if (RCLASS(rb_cObject)->iv_tbl) { 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) { if (arg.path == 0) {
st_foreach(rb_class_tbl, fc_i, (st_data_t)&arg); 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 (!generic_iv_tbl) return;
if (special_generic_ivar == 0) 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 void
@ -1118,7 +1118,7 @@ rb_obj_instance_variables(obj)
case T_CLASS: case T_CLASS:
case T_MODULE: case T_MODULE:
if (ROBJECT(obj)->iv_tbl) { 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; break;
default: default:
@ -1127,7 +1127,7 @@ rb_obj_instance_variables(obj)
st_table *tbl; st_table *tbl;
if (st_lookup(generic_iv_tbl, obj, (st_data_t *)&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; break;
@ -1511,7 +1511,7 @@ rb_mod_const_at(mod, data)
tbl = st_init_numtable(); tbl = st_init_numtable();
} }
if (RCLASS(mod)->iv_tbl) { 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; return tbl;
} }
@ -1875,7 +1875,7 @@ rb_mod_class_variables(obj)
for (;;) { for (;;) {
if (RCLASS(obj)->iv_tbl) { 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; obj = RCLASS(obj)->super;
if (!obj) break; if (!obj) break;