[ruby-dev:20412] Re: In 1.8.0 nil.to_s is not the same as ""
From:
nobu.nakada@...
Date:
2003-06-23 05:35:28 UTC
List:
ruby-dev #20412
なかだです。
At Mon, 23 Jun 2003 08:59:26 +0900,
Yukihiro Matsumoto wrote:
> |Well, all I found are attached.
> |
> |Not only NULL pointer access, contains fixes for:
> |* possible buffer overrun
> |* File.readlink truncated long symbolic link
> |* String#reverse! always returned self
>
> Incredible speed. After my change to use constant empty string, some
> of your fix is not needed. I will apply required fix. Thank you.
作り直しました。関係なくなってるので、スレッド切ってついでに(説
明がめんどくさいので)devへ。
* dir.c (find_dirsep): get rid of warnings.
qualifierを無視してるといって警告を出すコンパイラがあります。
gcc3だったかな?
* eval.c (error_print): temporary value might be disposed by GC.
一応念のため。
* eval.c (error_print): did not insert exception class path properly
when message had \0.
$ ./ruby -e 'class E<RuntimeError;def to_s;"\0"+super;end;end;raise E, "hello\n"'
-e:1: hello
(E)
んなことするなって気もしますが。
* file.c (rb_file_s_readlink): truncated long symbolic links.
$ ruby -e 'File.symlink("foo"*100, "foo"); p File.readlink("foo").length'
100
realloc()しても使ってません。
* hash.c (env_has_value, env_index): should not increment NULL.
NULLが返ってきても、+1してしまうと必ず真になってしまいますが、
たぶんSEGVに。実際に起きることはないと思いますが。
* io.c (io_read, rb_io_sysread): not read when length is 0.
今のところ、IO#readでバッファを渡してないときだけチェックして
ます。
* io.c (rb_io_s_sysopen): safety check for flags.
これも一応チェックしたほうがいいのではないかと。
* io.c (rb_io_reopen): ensure initialized IO.
$ ruby -e 'IO.allocate.reopen("/dev/null")'
-e:1: [BUG] Segmentation fault
ruby 1.8.0 (2003-06-21) [i686-linux]
アボートしました (core dumped)
IOはFlyweightよりもここでチェックしたほうがいいと思います。
* io.c (rb_io_init_copy): sychronize file pointer.
[ruby-talk:73292]の件。
* io.c (rb_io_s_pipe): make exception proof.
起きる条件は稀ですが、prep_stdio()の完了まではVALUEになってい
ないので、例外が起きるとパイプが放置されそうです。
* pack.c (pack_unpack): possible overrun.
$ ruby -e 'p "".unpack("@10000c")'
-e:1: [BUG] Segmentation fault
ruby 1.8.0 (2003-06-21) [i686-linux]
アボートしました (core dumped)
pack("p")と組み合わせると任意のアドレスにアクセス可能かも。
* string.c (rb_str_rindex_m): Fixnum 0 matched end of string.
$ ruby -e 'p "abc".rindex(0)'
3
ターミネータにマッチしてます。
Index: dir.c
===================================================================
RCS file: /cvs/ruby/src/ruby/dir.c,v
retrieving revision 1.85
diff -u -2 -p -r1.85 dir.c
--- dir.c 19 May 2003 15:54:37 -0000 1.85
+++ dir.c 22 Jun 2003 20:47:11 -0000
@@ -83,7 +84,7 @@ char *strchr _((char*,char));
#if defined DOSISH
#define isdirsep(c) ((c) == '/' || (c) == '\\')
-static char *
+static const char *
find_dirsep(s)
- char *s;
+ const char *s;
{
while (*s) {
Index: eval.c
===================================================================
RCS file: /cvs/ruby/src/ruby/eval.c,v
retrieving revision 1.466
diff -u -2 -p -r1.466 eval.c
--- eval.c 21 Jun 2003 17:15:53 -0000 1.466
+++ eval.c 22 Jun 2003 20:50:01 -0000
@@ -1035,5 +1035,5 @@ error_print()
{
VALUE errat = Qnil; /* OK */
- volatile VALUE eclass;
+ volatile VALUE eclass, e;
char *einfo;
long elen;
@@ -1070,5 +1070,5 @@ error_print()
eclass = CLASS_OF(ruby_errinfo);
if (EXEC_TAG() == 0) {
- VALUE e = rb_obj_as_string(ruby_errinfo);
+ e = rb_obj_as_string(ruby_errinfo);
einfo = RSTRING(e)->ptr;
elen = RSTRING(e)->len;
@@ -1095,5 +1095,5 @@ error_print()
if (RSTRING(epath)->ptr[0] == '#') epath = 0;
- if (tail = strchr(einfo, '\n')) {
+ if (tail = memchr(einfo, '\n', elen)) {
len = tail - einfo;
tail++; /* skip newline */
Index: file.c
===================================================================
RCS file: /cvs/ruby/src/ruby/file.c,v
retrieving revision 1.147
diff -u -2 -p -r1.147 file.c
--- file.c 20 Jun 2003 07:11:40 -0000 1.147
+++ file.c 22 Jun 2003 20:50:28 -0000
@@ -1276,5 +1276,5 @@ 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);
Index: hash.c
===================================================================
RCS file: /cvs/ruby/src/ruby/hash.c,v
retrieving revision 1.109
diff -u -2 -p -r1.109 hash.c
--- hash.c 20 Jun 2003 06:22:50 -0000 1.109
+++ hash.c 22 Jun 2003 20:51:53 -0000
@@ -1583,6 +1583,6 @@ env_has_value(dmy, value)
env = GET_ENVIRON(environ);
while (*env) {
- char *s = strchr(*env, '=')+1;
- if (s) {
+ char *s = strchr(*env, '=');
+ if (s++) {
#ifdef ENV_IGNORECASE
if (strncasecmp(s, RSTRING(value)->ptr, strlen(s)) == 0) {
@@ -1610,6 +1610,6 @@ env_index(dmy, value)
env = GET_ENVIRON(environ);
while (*env) {
- char *s = strchr(*env, '=')+1;
- if (s) {
+ char *s = strchr(*env, '=');
+ if (s++) {
#ifdef ENV_IGNORECASE
if (strncasecmp(s, RSTRING(value)->ptr, strlen(s)) == 0) {
Index: io.c
===================================================================
RCS file: /cvs/ruby/src/ruby/io.c,v
retrieving revision 1.213
diff -u -2 -p -r1.213 io.c
--- io.c 7 Jun 2003 15:33:40 -0000 1.213
+++ io.c 22 Jun 2003 20:58:00 -0000
@@ -824,5 +824,4 @@ io_read(argc, argv, io)
if (NIL_P(str)) {
str = rb_str_new(0, len);
- if (len == 0) return str;
}
else {
@@ -831,4 +830,5 @@ io_read(argc, argv, io)
rb_str_resize(str,len);
}
+ if (len == 0) return str;
READ_CHECK(fptr->f);
@@ -1574,4 +1574,5 @@ rb_io_sysread(argc, argv, io)
rb_str_resize(str, ilen);
}
+ if (ilen == 0) return str;
n = fileno(fptr->f);
@@ -2273,5 +2236,6 @@ rb_io_s_sysopen(argc, argv)
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;
@@ -2433,4 +2397,7 @@ rb_io_reopen(argc, argv, file)
rb_io_taint_check(file);
fptr = RFILE(file)->fptr;
+ if (!fptr) {
+ fptr = RFILE(file)->fptr = ALLOC(OpenFile);
+ }
if (!NIL_P(nmode)) {
@@ -2491,8 +2458,12 @@ rb_io_init_copy(dest, io)
if (orig->f2) {
io_fflush(orig->f2, orig);
+ fseeko(orig->f, 0L, SEEK_CUR);
}
else if (orig->mode & FMODE_WRITABLE) {
io_fflush(orig->f, orig);
}
+ else {
+ fseeko(orig->f, 0L, SEEK_CUR);
+ }
/* copy OpenFile structure */
@@ -3517,10 +3496,19 @@ rb_f_syscall(argc, argv)
}
+static VALUE io_new_instance _((VALUE));
+static VALUE
+io_new_instance(args)
+ VALUE args;
+{
+ return rb_class_new_instance(2, (VALUE*)args+1, *(VALUE*)args);
+}
+
static VALUE
-rb_io_s_pipe()
+rb_io_s_pipe(klass)
+ VALUE klass;
{
#ifndef __human68k__
- int pipes[2];
- VALUE r, w;
+ int pipes[2], state;
+ VALUE r, w, args[3];
#ifdef _WIN32
@@ -3531,6 +3519,22 @@ rb_io_s_pipe()
rb_sys_fail(0);
- r = prep_stdio(rb_fdopen(pipes[0], "r"), FMODE_READABLE, rb_cIO);
- w = prep_stdio(rb_fdopen(pipes[1], "w"), FMODE_WRITABLE|FMODE_SYNC, rb_cIO);
+ args[0] = klass;
+ args[1] = INT2NUM(pipes[0]);
+ args[2] = INT2FIX(O_RDONLY);
+ r = rb_protect(io_new_instance, (VALUE)args, &state);
+ if (state) {
+ close(pipes[0]);
+ close(pipes[1]);
+ rb_jump_tag(state);
+ }
+ args[1] = INT2NUM(pipes[1]);
+ args[2] = INT2FIX(O_WRONLY);
+ w = rb_protect(io_new_instance, (VALUE)args, &state);
+ if (state) {
+ close(pipes[1]);
+ if (!NIL_P(r)) rb_io_close(r);
+ rb_jump_tag(state);
+ }
+ rb_io_synchronized(RFILE(w)->fptr);
return rb_assoc_new(r, w);
Index: pack.c
===================================================================
RCS file: /cvs/ruby/src/ruby/pack.c,v
retrieving revision 1.53
diff -u -2 -p -r1.53 pack.c
--- pack.c 23 May 2003 06:16:20 -0000 1.53
+++ pack.c 22 Jun 2003 21:19:48 -0000
@@ -1678,4 +1678,6 @@ pack_unpack(str, fmt)
case '@':
+ if (len > RSTRING(str)->len)
+ rb_raise(rb_eArgError, "@ outside of string");
s = RSTRING(str)->ptr + len;
break;
Index: string.c
===================================================================
RCS file: /cvs/ruby/src/ruby/string.c,v
retrieving revision 1.156
diff -u -2 -p -r1.156 string.c
--- string.c 26 May 2003 08:22:28 -0000 1.156
+++ string.c 22 Jun 2003 21:07:30 -0000
@@ -1003,7 +994,6 @@ rb_str_rindex_m(argc, argv, str)
char *pbeg = RSTRING(str)->ptr;
- while (pbeg <= p) {
+ while (pbeg <= --p) {
if (*p == c) return LONG2NUM(p - RSTRING(str)->ptr);
- p--;
}
return Qnil;
--
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
中田 伸悦