From 1b4d97ddba6b3190a4aecad2c6159e6ecd63604e Mon Sep 17 00:00:00 2001 From: matz Date: Fri, 1 Oct 2004 15:56:05 +0000 Subject: [PATCH] * 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/trunk@6976 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 24 ++++++++++++++++++++++++ enum.c | 25 ++++++++++++------------- eval.c | 3 ++- file.c | 11 +++++------ gc.c | 14 +++++++------- io.c | 6 +++++- process.c | 2 +- re.c | 4 ++-- string.c | 34 ++++++++++++++++++++++++++-------- 9 files changed, 84 insertions(+), 39 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9d8b6a7a4e..5f4e1b6d8d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +Sat Oct 2 00:42:20 2004 Yukihiro Matsumoto + + * 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 diff --git a/enum.c b/enum.c index eee0e04291..b5de2a3fc2 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 b074ecb0c7..76726f012f 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; diff --git a/file.c b/file.c index 578274c6ce..36cb34a8cc 100644 --- a/file.c +++ b/file.c @@ -1729,8 +1729,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); @@ -2654,11 +2653,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)) @@ -2674,7 +2673,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; } @@ -2682,7 +2681,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/gc.c b/gc.c index fba3ee8fba..d3a7b477fc 100644 --- a/gc.c +++ b/gc.c @@ -92,7 +92,7 @@ static unsigned long malloc_increase = 0; static unsigned long malloc_limit = GC_MALLOC_LIMIT; static void run_final(); static VALUE nomem_error; -static void gc_internal(); +static void garbage_collect(); void rb_memerror() @@ -120,11 +120,11 @@ ruby_xmalloc(size) malloc_increase += size; if (malloc_increase > malloc_limit) { - gc_internal(); + garbage_collect(); } RUBY_CRITICAL(mem = malloc(size)); if (!mem) { - gc_internal(); + garbage_collect(); RUBY_CRITICAL(mem = malloc(size)); if (!mem) { rb_memerror(); @@ -161,7 +161,7 @@ ruby_xrealloc(ptr, size) malloc_increase += size; RUBY_CRITICAL(mem = realloc(ptr, size)); if (!mem) { - gc_internal(); + garbage_collect(); RUBY_CRITICAL(mem = realloc(ptr, size)); if (!mem) { rb_memerror(); @@ -381,7 +381,7 @@ rb_newobj() { VALUE obj; - if (!freelist) gc_internal(); + if (!freelist) garbage_collect(); obj = (VALUE)freelist; freelist = freelist->as.free.next; @@ -1288,7 +1288,7 @@ int rb_setjmp (rb_jmp_buf); #endif /* __GNUC__ */ static void -gc_internal() +garbage_collect() { struct gc_list *list; struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug?? */ @@ -1403,7 +1403,7 @@ gc_internal() void rb_gc() { - gc_internal(); + garbage_collect(); rb_gc_finalize_deferred(); } diff --git a/io.c b/io.c index ccd019f4f1..71273ed0b6 100644 --- a/io.c +++ b/io.c @@ -1194,11 +1194,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; @@ -2972,7 +2974,9 @@ rb_io_s_popen(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; } tmp = rb_check_array_type(pname); if (!NIL_P(tmp)) { diff --git a/process.c b/process.c index b7be36fbf7..c806250810 100644 --- a/process.c +++ b/process.c @@ -1207,8 +1207,8 @@ rb_check_argv(argc, argv) rb_raise(rb_eArgError, "wrong first argument"); } prog = RARRAY(tmp)->ptr[0]; - SafeStringValue(prog); argv[0] = RARRAY(tmp)->ptr[1]; + SafeStringValue(prog); } for (i = 0; i < argc; i++) { SafeStringValue(argv[i]); diff --git a/re.c b/re.c index 8fbd3b568a..ee5433015f 100644 --- a/re.c +++ b/re.c @@ -1722,8 +1722,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; @@ -1749,6 +1747,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 933c233a53..6f52434181 100644 --- a/string.c +++ b/string.c @@ -3139,7 +3139,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]; } } @@ -3598,6 +3598,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 @@ -3672,8 +3683,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; } } @@ -3843,11 +3853,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: @@ -3871,9 +3883,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') { @@ -4393,13 +4406,16 @@ rb_str_sum(argc, argv, str) VALUE vbits; int bits; char *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; + p = RSTRING(str)->ptr; + len = RSTRING(str)->len; + pend = p + len; if (bits > sizeof(long)*CHAR_BIT) { VALUE res = INT2FIX(0); VALUE mod; @@ -4408,6 +4424,7 @@ rb_str_sum(argc, argv, str) mod = rb_funcall(mod, '-', 1, INT2FIX(1)); while (p < pend) { + str_mod_check(str, p, len); res = rb_funcall(res, '+', 1, INT2FIX((unsigned int)*p)); p++; } @@ -4422,6 +4439,7 @@ rb_str_sum(argc, argv, str) mod = -1; } while (p < pend) { + str_mod_check(str, p, len); res += (unsigned int)*p; p++; }