diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2002-08-28 10:14:06 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2002-08-28 10:14:06 +0000 |
commit | 1b26d23f8023ae910ffa1ef37d3aca68662e2b59 (patch) | |
tree | 4a2492783243496b670ec8d046d42276135d7d45 /ext | |
parent | d159dbd9f49ed206112169d25f2afb8efd4cb2d2 (diff) | |
download | ruby-1b26d23f8023ae910ffa1ef37d3aca68662e2b59.tar.gz ruby-1b26d23f8023ae910ffa1ef37d3aca68662e2b59.tar.xz ruby-1b26d23f8023ae910ffa1ef37d3aca68662e2b59.zip |
* ext/stringio/stringio.c (strio_initialize): RSTRING(mode)->ptr
can be NULL.
* ext/stringio/stringio.c (strio_ungetc): fix buffer overflow.
git-svn-id: http://svn.ruby-lang.org/repos/ruby/trunk@2758 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext')
-rw-r--r-- | ext/stringio/stringio.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c index 6a50fabae..a6ba07307 100644 --- a/ext/stringio/stringio.c +++ b/ext/stringio/stringio.c @@ -205,6 +205,7 @@ strio_initialize(argc, argv, self) { struct StringIO *ptr = check_strio(self); VALUE string, mode; + const char* m; if (!ptr) { DATA_PTR(self) = ptr = strio_alloc(); @@ -214,12 +215,13 @@ strio_initialize(argc, argv, self) case 2: StringValue(mode); StringValue(string); - ptr->flags = rb_io_mode_flags(RSTRING(mode)->ptr); + if (!(m = RSTRING(mode)->ptr)) m = ""; + ptr->flags = rb_io_mode_flags(m); if (ptr->flags & FMODE_WRITABLE && OBJ_FROZEN(string)) { errno = EACCES; rb_sys_fail(0); } - switch (*RSTRING(mode)->ptr) { + switch (*m) { case 'a': ptr->flags |= STRIO_APPEND; break; @@ -543,14 +545,23 @@ strio_ungetc(self, ch) { struct StringIO *ptr = readable(StringIO(self)); int cc = NUM2INT(ch); + long len, pos = ptr->pos; - if (cc != EOF && ptr->pos > 0) { - if ((unsigned char)RSTRING(ptr->string)->ptr[--ptr->pos] != + if (cc != EOF && pos > 0) { + if ((len = RSTRING(ptr->string)->len) < pos || + (unsigned char)RSTRING(ptr->string)->ptr[pos - 1] != (unsigned char)cc) { check_modifiable(ptr); - rb_str_modify(ptr->string); - RSTRING(ptr->string)->ptr[ptr->pos] = cc; + if (len < pos) { + rb_str_resize(ptr->string, pos); + MEMZERO(RSTRING(ptr->string)->ptr + len, char, pos - len - 1); + } + else { + rb_str_modify(ptr->string); + } + RSTRING(ptr->string)->ptr[pos - 1] = cc; } + --ptr->pos; } return Qnil; } |