ruby-changes:41115
From: nobu <ko1@a...>
Date: Fri, 18 Dec 2015 16:54:41 +0900 (JST)
Subject: [ruby-changes:41115] nobu:r53188 (trunk): stringio.c: separate encoding from buffer
nobu 2015-12-18 16:54:33 +0900 (Fri, 18 Dec 2015) New Revision: 53188 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=53188 Log: stringio.c: separate encoding from buffer * ext/stringio/stringio.c (strio_set_encoding): add StringIO's own encoding and separate it from the buffer string to override the encoding of string when reading. [ruby-core:72189] [Bug #11827] note that setting the encoding of its buffer string may cause unpredictable behavior. Modified files: trunk/ChangeLog trunk/NEWS trunk/ext/stringio/stringio.c trunk/test/stringio/test_stringio.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 53187) +++ ChangeLog (revision 53188) @@ -1,3 +1,11 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Fri Dec 18 16:54:38 2015 Nobuyoshi Nakada <nobu@r...> + + * ext/stringio/stringio.c (strio_set_encoding): add StringIO's own + encoding and separate it from the buffer string to override the + encoding of string when reading. [ruby-core:72189] [Bug #11827] + note that setting the encoding of its buffer string may cause + unpredictable behavior. + Fri Dec 18 16:50:35 2015 Koichi Sasada <ko1@a...> * compile.c (ibf_load_setup): check tainted string argument. Index: ext/stringio/stringio.c =================================================================== --- ext/stringio/stringio.c (revision 53187) +++ ext/stringio/stringio.c (revision 53188) @@ -22,6 +22,7 @@ https://github.com/ruby/ruby/blob/trunk/ext/stringio/stringio.c#L22 struct StringIO { VALUE string; + rb_encoding *enc; long pos; long lineno; int flags; @@ -33,6 +34,7 @@ static VALUE strio_unget_bytes(struct St https://github.com/ruby/ruby/blob/trunk/ext/stringio/stringio.c#L34 #define IS_STRIO(obj) (rb_typeddata_is_kind_of((obj), &strio_data_type)) #define error_inval(msg) (errno = EINVAL, rb_sys_fail(msg)) +#define get_enc(ptr) ((ptr)->enc ? (ptr)->enc : rb_enc_get((ptr)->string)) static struct StringIO * strio_alloc(void) @@ -97,7 +99,7 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/ext/stringio/stringio.c#L99 strio_substr(struct StringIO *ptr, long pos, long len) { VALUE str = ptr->string; - rb_encoding *enc = rb_enc_get(str); + rb_encoding *enc = get_enc(ptr); long rlen = RSTRING_LEN(str) - pos; if (len > rlen) len = rlen; @@ -210,6 +212,7 @@ strio_init(int argc, VALUE *argv, struct https://github.com/ruby/ruby/blob/trunk/ext/stringio/stringio.c#L212 break; } ptr->string = string; + ptr->enc = 0; ptr->pos = 0; ptr->lineno = 0; RBASIC(self)->flags |= (ptr->flags & FMODE_READWRITE) * (STRIO_READABLE / FMODE_READABLE); @@ -663,7 +666,7 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/ext/stringio/stringio.c#L666 strio_getc(VALUE self) { struct StringIO *ptr = readable(self); - rb_encoding *enc = rb_enc_get(ptr->string); + rb_encoding *enc = get_enc(ptr); int len; char *p; @@ -673,7 +676,7 @@ strio_getc(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/stringio/stringio.c#L676 p = RSTRING_PTR(ptr->string)+ptr->pos; len = rb_enc_mbclen(p, RSTRING_END(ptr->string), enc); ptr->pos += len; - return rb_enc_str_new(p, len, rb_enc_get(ptr->string)); + return rb_enc_str_new(p, len, enc); } /* @@ -888,7 +891,7 @@ strio_each_codepoint(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/stringio/stringio.c#L891 RETURN_ENUMERATOR(self, 0, 0); ptr = readable(self); - enc = rb_enc_get(ptr->string); + enc = get_enc(ptr); for (;;) { if (ptr->pos >= RSTRING_LEN(ptr->string)) { return self; @@ -987,7 +990,7 @@ strio_getline(int argc, VALUE *argv, str https://github.com/ruby/ruby/blob/trunk/ext/stringio/stringio.c#L990 e = s + RSTRING_LEN(ptr->string); s += ptr->pos; if (limit > 0 && s + limit < e) { - e = rb_enc_right_char_head(s, s + limit, e, rb_enc_get(ptr->string)); + e = rb_enc_right_char_head(s, s + limit, e, get_enc(ptr)); } if (NIL_P(str)) { str = strio_substr(ptr, ptr->pos, e - s); @@ -1164,7 +1167,7 @@ strio_write(VALUE self, VALUE str) https://github.com/ruby/ruby/blob/trunk/ext/stringio/stringio.c#L1167 if (!RB_TYPE_P(str, T_STRING)) str = rb_obj_as_string(str); - enc = rb_enc_get(ptr->string); + enc = get_enc(ptr); enc2 = rb_enc_get(str); if (enc != enc2 && enc != ascii8bit) { str = rb_str_conv_enc(str, enc2, enc); @@ -1439,7 +1442,8 @@ strio_truncate(VALUE self, VALUE len) https://github.com/ruby/ruby/blob/trunk/ext/stringio/stringio.c#L1442 static VALUE strio_external_encoding(VALUE self) { - return rb_enc_from_encoding(rb_enc_get(StringIO(self)->string)); + struct StringIO *ptr = StringIO(self); + return rb_enc_from_encoding(get_enc(ptr)); } /* @@ -1470,7 +1474,7 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/ext/stringio/stringio.c#L1474 strio_set_encoding(int argc, VALUE *argv, VALUE self) { rb_encoding* enc; - VALUE str = StringIO(self)->string; + struct StringIO *ptr = StringIO(self); VALUE ext_enc, int_enc, opt; argc = rb_scan_args(argc, argv, "11:", &ext_enc, &int_enc, &opt); @@ -1481,7 +1485,11 @@ strio_set_encoding(int argc, VALUE *argv https://github.com/ruby/ruby/blob/trunk/ext/stringio/stringio.c#L1485 else { enc = rb_to_encoding(ext_enc); } - rb_enc_associate(str, enc); + ptr->enc = enc; + if (WRITABLE(self)) { + rb_enc_associate(ptr->string, enc); + } + return self; } Index: NEWS =================================================================== --- NEWS (revision 53187) +++ NEWS (revision 53188) @@ -239,6 +239,11 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L239 String buffer argument like IO#read and IO#read_nonblock to reduce GC overhead +* StringIO + * In read-only mode, StringIO#set_encoding no longer sets the encoding + of its buffer string. Setting the encoding of the string directly + may cause unpredictable behavior. [Bug #11827] + * timeout * Object#timeout is now warned as deprecated when called. Index: test/stringio/test_stringio.rb =================================================================== --- test/stringio/test_stringio.rb (revision 53187) +++ test/stringio/test_stringio.rb (revision 53188) @@ -148,6 +148,13 @@ class TestStringIO < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/stringio/test_stringio.rb#L148 f.write(s) } assert_equal(Encoding::ASCII_8BIT, f.string.encoding, bug10285) + + bug11827 = '[ruby-core:72189] [Bug #11827]' + f = StringIO.new("foo\x83".freeze) + assert_nothing_raised(RuntimeError, bug11827) { + f.set_encoding(Encoding::ASCII_8BIT) + } + assert_equal("foo\x83".b, f.gets) end def test_mode_error -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/