From 67dcad92b7fb9f8b95c8e4925061527fc8a8db3d Mon Sep 17 00:00:00 2001 From: matz Date: Mon, 23 Jun 2003 06:52:39 +0000 Subject: * string.c (rb_str_upto): generate sequence according to "succ" order. formerly check was done by dictionary order. [ruby-talk:74138] * string.c (rb_string_value): fill constant empty string along with setting ELTS_SHARED if str->ptr is NULL. [ruby-core:01179] * string.c (rb_string_value_ptr): ditto. * string.c (rb_check_string_type): ditto. * string.c (str_gsub): move END(0) check before mbclen2(). * string.c (scan_once): reduce END(0) check. * io.c (rb_io_initialize): accept fixnum mode. * eval.c (error_print): replace strchr() by memchr(), einfo may contain "\0". * pack.c (pack_unpack): range check for "@" move; initialize check for "m". * error.c (syserr_initialize): avoid buffer overflow. * file.c (rb_file_s_readlink): expand buffer until readlink succeed. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3982 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 34 ++++++++++++++++++++++++++++++++++ dln.c | 1 + error.c | 2 +- eval.c | 8 ++++---- file.c | 2 +- hash.c | 14 ++++++-------- io.c | 20 ++++++++++++++++---- pack.c | 22 ++++++++++++---------- ruby.c | 9 +++++---- ruby.h | 2 +- string.c | 46 ++++++++++++++++++++++++++++++++-------------- 11 files changed, 113 insertions(+), 47 deletions(-) diff --git a/ChangeLog b/ChangeLog index a5e6bc2aa4..b931484b2c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,40 @@ Mon Jun 23 13:45:30 2003 Tanaka Akira * time.c (time_arg): initialize v[6] even when argc is 10 to avoid valgrind error. +Mon Jun 23 08:24:01 2003 Florian Frank + + * string.c (rb_str_upto): generate sequence according to "succ" + order. formerly check was done by dictionary order. + [ruby-talk:74138] + +Mon Jun 23 00:27:32 2003 Yukihiro Matsumoto + + * string.c (rb_string_value): fill constant empty string along + with setting ELTS_SHARED if str->ptr is NULL. [ruby-core:01179] + + * string.c (rb_string_value_ptr): ditto. + + * string.c (rb_check_string_type): ditto. + +Sun Jun 22 23:42:20 2003 Nobuyoshi Nakada + + * string.c (str_gsub): move END(0) check before mbclen2(). + + * string.c (scan_once): reduce END(0) check. + + * io.c (rb_io_initialize): accept fixnum mode. + + * eval.c (error_print): replace strchr() by memchr(), einfo may + contain "\0". + + * pack.c (pack_unpack): range check for "@" move; initialize check + for "m". + + * error.c (syserr_initialize): avoid buffer overflow. + + * file.c (rb_file_s_readlink): expand buffer until readlink + succeed. + Sat Jun 21 23:15:08 2003 Yukihiro Matsumoto * eval.c (proc_invoke): should not propagate distination tag if diff --git a/dln.c b/dln.c index f6950e1863..267b9f64e8 100644 --- a/dln.c +++ b/dln.c @@ -1662,6 +1662,7 @@ dln_find_1(fname, path, exe_flag) const char* mac_fullpath; #endif + if (!fname) return fname; if (fname[0] == '/') return fname; if (strncmp("./", fname, 2) == 0 || strncmp("../", fname, 3) == 0) return fname; diff --git a/error.c b/error.c index d9c673c807..f62150f3e5 100644 --- a/error.c +++ b/error.c @@ -582,7 +582,7 @@ syserr_initialize(argc, argv, self) if (!NIL_P(mesg)) { StringValue(mesg); buf = ALLOCA_N(char, strlen(err)+RSTRING(mesg)->len+4); - sprintf(buf, "%s - %s", err, RSTRING(mesg)->ptr); + sprintf(buf, "%s - %.*s", err, RSTRING(mesg)->len, RSTRING(mesg)->ptr); mesg = rb_str_new2(buf); } else { diff --git a/eval.c b/eval.c index 6f95f0fc9a..4186b2e9e3 100644 --- a/eval.c +++ b/eval.c @@ -1094,7 +1094,7 @@ error_print() long len = elen; if (RSTRING(epath)->ptr[0] == '#') epath = 0; - if (tail = strchr(einfo, '\n')) { + if (tail = memchr(einfo, '\n', elen)) { len = tail - einfo; tail++; /* skip newline */ } @@ -3357,11 +3357,11 @@ rb_eval(self, n) switch (nd_type(node)) { case NODE_DREGX: result = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len, - node->nd_cflag); + node->nd_cflag); break; case NODE_DREGX_ONCE: /* regexp expand once */ result = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len, - node->nd_cflag); + node->nd_cflag); nd_set_type(node, NODE_LIT); node->nd_lit = result; break; @@ -4673,7 +4673,7 @@ rb_f_missing(argc, argv, obj) *ruby_frame = *_frame.prev->prev; { char buf[BUFSIZ]; - int noclass = (!d || desc[0]=='#'); + int noclass = (!desc || desc[0]=='#'); int n = 0; VALUE args[3]; diff --git a/file.c b/file.c index 156b329f86..ad14138731 100644 --- a/file.c +++ b/file.c @@ -1275,7 +1275,7 @@ rb_file_s_readlink(klass, path) SafeStringValue(path); buf = xmalloc(size); - if ((rv = readlink(RSTRING(path)->ptr, buf, size)) == size) { + while ((rv = readlink(RSTRING(path)->ptr, buf, size)) == size) { size *= 2; buf = xrealloc(buf, size); } diff --git a/hash.c b/hash.c index cf7a14bb34..8f636e1590 100644 --- a/hash.c +++ b/hash.c @@ -997,6 +997,7 @@ static VALUE env_str_new2(ptr) const char *ptr; { + if (!ptr) return Qnil; return env_str_new(ptr, strlen(ptr)); } @@ -1606,7 +1607,7 @@ env_index(dmy, value) char **env; VALUE str; - if (TYPE(value) != T_STRING) return Qnil; + StringValue(value); env = GET_ENVIRON(environ); while (*env) { char *s = strchr(*env, '=')+1; @@ -1638,15 +1639,12 @@ env_indexes(argc, argv) rb_warn("ENV.%s is deprecated; use ENV.values_at", rb_id2name(rb_frame_last_func())); for (i=0;iptr); - } - if (v) { - RARRAY(indexes)->ptr[i] = env_str_new2(v); + VALUE tmp = rb_check_string_type(argv[i]); + if (NIL_P(tmp)) { + RARRAY(indexes)->ptr[i] = Qnil; } else { - RARRAY(indexes)->ptr[i] = Qnil; + RARRAY(indexes)->ptr[i] = env_str_new2(getenv(RSTRING(tmp)->ptr)); } RARRAY(indexes)->len = i+1; } diff --git a/io.c b/io.c index 8fac72a0ce..662930a353 100644 --- a/io.c +++ b/io.c @@ -2231,7 +2231,13 @@ rb_open_file(argc, argv, io) path = RSTRING(fname)->ptr; if (FIXNUM_P(vmode) || !NIL_P(perm)) { - flags = FIXNUM_P(vmode) ? NUM2INT(vmode) : rb_io_mode_modenum(StringValuePtr(vmode)); + if (FIXNUM_P(vmode)) { + flags = NUM2INT(vmode); + } + else { + SafeStringValue(vmode); + rb_io_mode_modenum(RSTRING(vmode)->ptr); + } fmode = NIL_P(perm) ? 0666 : NUM2INT(perm); rb_file_sysopen_internal(io, path, flags, fmode); @@ -2272,7 +2278,8 @@ rb_io_s_sysopen(argc, argv) if (NIL_P(vmode)) flags = O_RDONLY; else if (FIXNUM_P(vmode)) flags = NUM2INT(vmode); else { - flags = rb_io_mode_modenum(StringValuePtr(vmode)); + SafeStringValue(vmode); + flags = rb_io_mode_modenum(RSTRING(vmode)->ptr); } if (NIL_P(perm)) fmode = 0666; else fmode = NUM2INT(perm); @@ -2833,8 +2840,13 @@ rb_io_initialize(argc, argv, io) rb_scan_args(argc, argv, "11", &fnum, &mode); fd = NUM2INT(fnum); if (argc == 2) { - SafeStringValue(mode); - flags = rb_io_mode_modenum(RSTRING(mode)->ptr); + if (FIXNUM_P(mode)) { + flags = FIX2LONG(mode); + } + else { + SafeStringValue(mode); + flags = rb_io_mode_modenum(RSTRING(mode)->ptr); + } } else { #if defined(HAVE_FCNTL) && defined(F_GETFL) diff --git a/pack.c b/pack.c index b0b51c1b2a..86726518ce 100644 --- a/pack.c +++ b/pack.c @@ -889,8 +889,7 @@ pack_pack(ary, fmt) t = 0; } else { - StringValue(from); - t = RSTRING(from)->ptr; + t = StringValuePtr(from); } if (!associates) { associates = rb_ary_new(); @@ -1610,7 +1609,7 @@ pack_unpack(str, fmt) { VALUE buf = infected_str_new(0, (send - s)*3/4, str); char *ptr = RSTRING(buf)->ptr; - int a,b,c = 0,d; + int a = -1,b = -1,c = 0,d; static int first = 1; static int b64_xtable[256]; @@ -1625,7 +1624,7 @@ pack_unpack(str, fmt) b64_xtable[(int)b64_table[i]] = i; } } - for (;;) { + while (s < send) { while (s[0] == '\r' || s[0] == '\n') { s++; } if ((a = b64_xtable[(int)s[0]]) == -1) break; if ((b = b64_xtable[(int)s[1]]) == -1) break; @@ -1636,12 +1635,13 @@ pack_unpack(str, fmt) *ptr++ = c << 6 | d; s += 4; } - if (a != -1 && b != -1 && s[2] == '=') { - *ptr++ = a << 2 | b >> 4; - } - if (a != -1 && b != -1 && c != -1 && s[3] == '=') { - *ptr++ = a << 2 | b >> 4; - *ptr++ = b << 4 | c >> 2; + if (a != -1 && b != -1) { + if (s + 2 < send && s[2] == '=') + *ptr++ = a << 2 | b >> 4; + if (c != -1 && s + 3 < send && s[3] == '=') { + *ptr++ = a << 2 | b >> 4; + *ptr++ = b << 4 | c >> 2; + } } *ptr = '\0'; RSTRING(buf)->len = ptr - RSTRING(buf)->ptr; @@ -1677,6 +1677,8 @@ pack_unpack(str, fmt) break; case '@': + if (len > RSTRING(str)->len) + rb_raise(rb_eArgError, "@ outside of string"); s = RSTRING(str)->ptr + len; break; diff --git a/ruby.c b/ruby.c index f48898e3f1..0437b5bb04 100644 --- a/ruby.c +++ b/ruby.c @@ -704,8 +704,8 @@ proc_options(argc, argv) } if (rb_safe_level() >= 4) { - OBJ_TAINT(rb_argv); - OBJ_TAINT(rb_load_path); + OBJ_TAINT(rb_argv); + OBJ_TAINT(rb_load_path); } if (!e_script) { @@ -758,8 +758,8 @@ proc_options(argc, argv) xflag = 0; if (rb_safe_level() >= 4) { - FL_UNSET(rb_argv, FL_TAINT); - FL_UNSET(rb_load_path, FL_TAINT); + FL_UNSET(rb_argv, FL_TAINT); + FL_UNSET(rb_load_path, FL_TAINT); } } @@ -774,6 +774,7 @@ load_file(fname, script) VALUE f; int line_start = 1; + if (!fname) rb_load_fail(fname); if (strcmp(fname, "-") == 0) { f = rb_stdin; } diff --git a/ruby.h b/ruby.h index 76ea5d8b7c..ee6f572c5f 100644 --- a/ruby.h +++ b/ruby.h @@ -214,7 +214,7 @@ VALUE rb_str_to_str _((VALUE)); VALUE rb_string_value _((volatile VALUE*)); char *rb_string_value_ptr _((volatile VALUE*)); -#define StringValue(v) if (TYPE(v) != T_STRING) rb_string_value(&(v)) +#define StringValue(v) rb_string_value(&(v)) #define StringValuePtr(v) rb_string_value_ptr(&(v)) void rb_check_safe_obj _((VALUE)); diff --git a/string.c b/string.c index 0bbd9f5513..eed7a0e887 100644 --- a/string.c +++ b/string.c @@ -158,7 +158,7 @@ rb_str_new4(orig) VALUE klass, str; klass = rb_obj_class(orig); - if (FL_TEST(orig, ELTS_SHARED)) { + if (FL_TEST(orig, ELTS_SHARED) && RSTRING(orig)->aux.shared) { long ofs; str = RSTRING(orig)->aux.shared; ofs = RSTRING(str)->len - RSTRING(orig)->len; @@ -445,11 +445,18 @@ rb_str_associated(str) return Qfalse; } +static char *null_str = ""; + VALUE rb_string_value(ptr) volatile VALUE *ptr; { - return *ptr = rb_str_to_str(*ptr); + *ptr = rb_str_to_str(*ptr); + if (!RSTRING(*ptr)->ptr) { + FL_SET(*ptr, ELTS_SHARED); + RSTRING(*ptr)->ptr = null_str; + } + return *ptr; } char * @@ -462,7 +469,8 @@ rb_string_value_ptr(ptr) *ptr = s; } if (!RSTRING(s)->ptr) { - str_make_independent(s); + FL_SET(s, ELTS_SHARED); + RSTRING(s)->ptr = null_str; } return RSTRING(s)->ptr; } @@ -471,7 +479,12 @@ VALUE rb_check_string_type(str) VALUE str; { - return rb_check_convert_type(str, T_STRING, "String", "to_str"); + str = rb_check_convert_type(str, T_STRING, "String", "to_str"); + if (!NIL_P(str) && !RSTRING(str)->ptr) { + FL_SET(str, ELTS_SHARED); + RSTRING(str)->ptr = null_str; + } + return str; } VALUE @@ -498,7 +511,7 @@ rb_str_substr(str, beg, len) if (len > sizeof(struct RString)/2 && beg + len == RSTRING(str)->len && !FL_TEST(str, STR_ASSOC)) { - if (FL_TEST(str, ELTS_SHARED)) + if (FL_TEST(str, ELTS_SHARED) && RSTRING(str)->aux.shared) str = RSTRING(str)->aux.shared; else str = str_new4(rb_obj_class(str), str); @@ -525,7 +538,7 @@ VALUE rb_str_dup_frozen(str) VALUE str; { - if (FL_TEST(str, ELTS_SHARED)) { + if (FL_TEST(str, ELTS_SHARED) && RSTRING(str)->aux.shared) { VALUE shared = RSTRING(str)->aux.shared; if (RSTRING(shared)->len == RSTRING(str)->len) { OBJ_FREEZE(shared); @@ -1142,12 +1155,14 @@ rb_str_upto(beg, end, excl) VALUE beg, end; int excl; { - VALUE current; + VALUE current, after_end; ID succ = rb_intern("succ"); StringValue(end); + if (rb_str_cmp(beg, end) > 0) return beg; + after_end = rb_funcall(end, succ, 0, 0); current = beg; - while (rb_str_cmp(current, end) <= 0) { + while (!rb_str_equal(current, after_end)) { rb_yield(current); if (!excl && rb_str_equal(current, end)) break; current = rb_funcall(current, succ, 0, 0); @@ -1163,7 +1178,7 @@ static VALUE rb_str_upto_m(beg, end) VALUE beg, end; { - return rb_str_upto(beg, end, 0); + return rb_str_upto(beg, end, Qfalse); } static VALUE @@ -1615,11 +1630,10 @@ str_gsub(argc, argv, str, bang) * Always consume at least one character of the input string * in order to prevent infinite loops. */ + if (RSTRING(str)->len <= END(0)) break; len = mbclen2(RSTRING(str)->ptr[END(0)], pat); - if (RSTRING(str)->len > END(0)) { - memcpy(bp, RSTRING(str)->ptr+END(0), len); - bp += len; - } + memcpy(bp, RSTRING(str)->ptr+END(0), len); + bp += len; offset = END(0) + len; } else { @@ -1770,6 +1784,7 @@ rb_str_reverse_bang(str) char *s, *e; char c; + if (RSTRING(str)->len <= 1) return Qnil; rb_str_modify(str); s = RSTRING(str)->ptr; e = s + RSTRING(str)->len - 1; @@ -2976,7 +2991,10 @@ scan_once(str, pat, start) /* * Always consume at least one character of the input string */ - *start = END(0)+mbclen2(RSTRING(str)->ptr[END(0)],pat); + if (RSTRING(str)->len < END(0)) + *start = END(0)+mbclen2(RSTRING(str)->ptr[END(0)],pat); + else + *start = END(0)+1; } else { *start = END(0); -- cgit v1.2.3