Bug #2696 [ruby-dev:40271]
rubyspec: StringIO#ungetc when passed [char] pads with \000 when the current position is after the end ERROR
| Status : | Closed | Start : | ||
| Priority : | Normal | Due date : | ||
| Assigned to : | Nobuyoshi Nakada | % Done : | 100% |
|
| Category : | - | |||
| Target version : | - | |||
| ruby -v : | nil |
Description
stringio のメンテナのなかださん、もしくはまつもとさん
遠藤です。
stringio に関して、バッファ終端より先に pos を合わせた状態で
StringIO#ungetc を呼んだ時の挙動が 1.8 と 1.9 で違います。
# 1.8 では間が \0 で埋められる
$ ruby18 -rstringio -e '
io = StringIO.new("1234")
io.pos = 15
io.ungetc(?A)
p io.string
'
"1234\000\000\000\000\000\000\000\000\000\000A"
# 1.9 では例外になる
$ ./ruby -rstringio -e '
io = StringIO.new("1234")
io.pos = 15
io.ungetc(?A)
p io.string
'
-e:4:in `ungetc': index 14 out of string (IndexError)
from -e:4:in `<main>'
r13261 が原因のようです。この挙動の変更を狙ったものではない
ような気がしますが、いかがでしょうか。
--
Yusuke ENDOH <mame@tsg.ne.jp>
Associated revisions
- ext/stringio/stringio.c (strio_ungetc): pads with \000 when the
current position is after the end.
[ruby-dev:40271]
History
02/04/2010 02:01 AM - ujihisa .
- Status changed from Open to Assigned
- Assigned to set to Nobuyoshi Nakada
02/05/2010 03:46 AM - Yusuke Endoh
遠藤です。 2010年1月31日19:21 Yusuke ENDOH <mame@tsg.ne.jp>: > stringio に関して、バッファ終端より先に pos を合わせた状態で > StringIO#ungetc を呼んだ時の挙動が 1.8 と 1.9 で違います。 > > > # 1.8 では間が \0 で埋められる > $ ruby18 -rstringio -e ' > io = StringIO.new("1234") > io.pos = 15 > io.ungetc(?A) > p io.string > ' > "1234\000\000\000\000\000\000\000\000\000\000A" > > > # 1.9 では例外になる > $ ./ruby -rstringio -e ' > io = StringIO.new("1234") > io.pos = 15 > io.ungetc(?A) > p io.string > ' > -e:4:in `ungetc': index 14 out of string (IndexError) > from -e:4:in `<main>' > > > r13261 が原因のようです。この挙動の変更を狙ったものではない > ような気がしますが、いかがでしょうか。 成瀬さんの監修のもと、パッチを書いてみました。 反対がなければコミットしてしまいます。 diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c index f193c6e..faf974e 100644 --- a/ext/stringio/stringio.c +++ b/ext/stringio/stringio.c @@ -725,17 +725,26 @@ strio_ungetc(VALUE self, VALUE c) c = rb_str_conv_enc(c, enc2, enc); } } - /* get logical position */ - lpos = 0; p = RSTRING_PTR(ptr->string); pend = p + ptr->pos; - for (;;) { - clen = rb_enc_mbclen(p, pend, enc); - if (p+clen >= pend) break; - p += clen; - lpos++; + if (RSTRING_LEN(ptr->string) < ptr->pos) { + long len = RSTRING_LEN(ptr->string); + rb_str_resize(ptr->string, ptr->pos - 1); + memset(RSTRING_PTR(ptr->string) + len, 0, ptr->pos - len - 1); + rb_str_concat(ptr->string, c); + ptr->pos--; + } + else { + /* get logical position */ + lpos = 0; p = RSTRING_PTR(ptr->string); pend = p + ptr->pos; + for (;;) { + clen = rb_enc_mbclen(p, pend, enc); + if (p+clen >= pend) break; + p += clen; + lpos++; + } + clen = p - RSTRING_PTR(ptr->string); + rb_str_update(ptr->string, lpos, ptr->pos ? 1 : 0, c); + ptr->pos = clen; } - clen = p - RSTRING_PTR(ptr->string); - rb_str_update(ptr->string, lpos, ptr->pos ? 1 : 0, c); - ptr->pos = clen; return Qnil; } -- Yusuke ENDOH <mame@tsg.ne.jp>