summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-08-28 10:14:06 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-08-28 10:14:06 +0000
commit343f505fb8a6162d2a3ecbef360813eec81f221c (patch)
tree4a2492783243496b670ec8d046d42276135d7d45 /ext
parent4c59a65d045313fd6233b71fcec126f8d4b81575 (diff)
* ext/stringio/stringio.c (strio_initialize): RSTRING(mode)->ptr
can be NULL. * ext/stringio/stringio.c (strio_ungetc): fix buffer overflow. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2758 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext')
-rw-r--r--ext/stringio/stringio.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c
index 6a50fabaed..a6ba07307e 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;
}