[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]