Project

General

Profile

Actions

Bug #2696

closed

rubyspec: StringIO#ungetc when passed [char] pads with \000 when the current position is after the end ERROR

Added by mame (Yusuke Endoh) over 15 years ago. Updated over 14 years ago.

Status:
Closed
Target version:
-
ruby -v:
nil
Backport:
[ruby-dev:40271]

Description

=begin
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 '

r13261 が原因のようです。この挙動の変更を狙ったものではない
ような気がしますが、いかがでしょうか。

--
Yusuke ENDOH
=end

Actions #1

Updated by naruse (Yui NARUSE) over 15 years ago

  • Priority changed from 3 to Normal
  • ruby -v set to nil

=begin

=end

Actions #2

Updated by ujihisa (Tatsuhiro Ujihisa) over 15 years ago

  • Status changed from Open to Assigned
  • Assignee set to nobu (Nobuyoshi Nakada)

=begin

=end

Actions #3

Updated by mame (Yusuke Endoh) over 15 years ago

=begin
遠藤です。

2010年1月31日19:21 Yusuke ENDOH :

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 '

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

=end

Actions #4

Updated by mame (Yusuke Endoh) over 15 years ago

  • Status changed from Assigned to Closed
  • % Done changed from 0 to 100

=begin
This issue was solved with changeset r26588.
Yusuke, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.

=end

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0