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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53188 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
dd5fd65eef
commit
3e1c01ae46
@ -1,3 +1,11 @@
|
|||||||
|
Fri Dec 18 16:54:38 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* 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@atdot.net>
|
Fri Dec 18 16:50:35 2015 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
* compile.c (ibf_load_setup): check tainted string argument.
|
* compile.c (ibf_load_setup): check tainted string argument.
|
||||||
|
5
NEWS
5
NEWS
@ -239,6 +239,11 @@ with all sufficient information, see the ChangeLog file.
|
|||||||
String buffer argument like IO#read and IO#read_nonblock to reduce
|
String buffer argument like IO#read and IO#read_nonblock to reduce
|
||||||
GC overhead
|
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
|
* timeout
|
||||||
* Object#timeout is now warned as deprecated when called.
|
* Object#timeout is now warned as deprecated when called.
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
struct StringIO {
|
struct StringIO {
|
||||||
VALUE string;
|
VALUE string;
|
||||||
|
rb_encoding *enc;
|
||||||
long pos;
|
long pos;
|
||||||
long lineno;
|
long lineno;
|
||||||
int flags;
|
int flags;
|
||||||
@ -33,6 +34,7 @@ static VALUE strio_unget_bytes(struct StringIO *, const char *, long);
|
|||||||
|
|
||||||
#define IS_STRIO(obj) (rb_typeddata_is_kind_of((obj), &strio_data_type))
|
#define IS_STRIO(obj) (rb_typeddata_is_kind_of((obj), &strio_data_type))
|
||||||
#define error_inval(msg) (errno = EINVAL, rb_sys_fail(msg))
|
#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 *
|
static struct StringIO *
|
||||||
strio_alloc(void)
|
strio_alloc(void)
|
||||||
@ -97,7 +99,7 @@ static VALUE
|
|||||||
strio_substr(struct StringIO *ptr, long pos, long len)
|
strio_substr(struct StringIO *ptr, long pos, long len)
|
||||||
{
|
{
|
||||||
VALUE str = ptr->string;
|
VALUE str = ptr->string;
|
||||||
rb_encoding *enc = rb_enc_get(str);
|
rb_encoding *enc = get_enc(ptr);
|
||||||
long rlen = RSTRING_LEN(str) - pos;
|
long rlen = RSTRING_LEN(str) - pos;
|
||||||
|
|
||||||
if (len > rlen) len = rlen;
|
if (len > rlen) len = rlen;
|
||||||
@ -210,6 +212,7 @@ strio_init(int argc, VALUE *argv, struct StringIO *ptr, VALUE self)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ptr->string = string;
|
ptr->string = string;
|
||||||
|
ptr->enc = 0;
|
||||||
ptr->pos = 0;
|
ptr->pos = 0;
|
||||||
ptr->lineno = 0;
|
ptr->lineno = 0;
|
||||||
RBASIC(self)->flags |= (ptr->flags & FMODE_READWRITE) * (STRIO_READABLE / FMODE_READABLE);
|
RBASIC(self)->flags |= (ptr->flags & FMODE_READWRITE) * (STRIO_READABLE / FMODE_READABLE);
|
||||||
@ -663,7 +666,7 @@ static VALUE
|
|||||||
strio_getc(VALUE self)
|
strio_getc(VALUE self)
|
||||||
{
|
{
|
||||||
struct StringIO *ptr = readable(self);
|
struct StringIO *ptr = readable(self);
|
||||||
rb_encoding *enc = rb_enc_get(ptr->string);
|
rb_encoding *enc = get_enc(ptr);
|
||||||
int len;
|
int len;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
@ -673,7 +676,7 @@ strio_getc(VALUE self)
|
|||||||
p = RSTRING_PTR(ptr->string)+ptr->pos;
|
p = RSTRING_PTR(ptr->string)+ptr->pos;
|
||||||
len = rb_enc_mbclen(p, RSTRING_END(ptr->string), enc);
|
len = rb_enc_mbclen(p, RSTRING_END(ptr->string), enc);
|
||||||
ptr->pos += len;
|
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)
|
|||||||
RETURN_ENUMERATOR(self, 0, 0);
|
RETURN_ENUMERATOR(self, 0, 0);
|
||||||
|
|
||||||
ptr = readable(self);
|
ptr = readable(self);
|
||||||
enc = rb_enc_get(ptr->string);
|
enc = get_enc(ptr);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (ptr->pos >= RSTRING_LEN(ptr->string)) {
|
if (ptr->pos >= RSTRING_LEN(ptr->string)) {
|
||||||
return self;
|
return self;
|
||||||
@ -987,7 +990,7 @@ strio_getline(int argc, VALUE *argv, struct StringIO *ptr)
|
|||||||
e = s + RSTRING_LEN(ptr->string);
|
e = s + RSTRING_LEN(ptr->string);
|
||||||
s += ptr->pos;
|
s += ptr->pos;
|
||||||
if (limit > 0 && s + limit < e) {
|
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)) {
|
if (NIL_P(str)) {
|
||||||
str = strio_substr(ptr, ptr->pos, e - s);
|
str = strio_substr(ptr, ptr->pos, e - s);
|
||||||
@ -1164,7 +1167,7 @@ strio_write(VALUE self, VALUE str)
|
|||||||
|
|
||||||
if (!RB_TYPE_P(str, T_STRING))
|
if (!RB_TYPE_P(str, T_STRING))
|
||||||
str = rb_obj_as_string(str);
|
str = rb_obj_as_string(str);
|
||||||
enc = rb_enc_get(ptr->string);
|
enc = get_enc(ptr);
|
||||||
enc2 = rb_enc_get(str);
|
enc2 = rb_enc_get(str);
|
||||||
if (enc != enc2 && enc != ascii8bit) {
|
if (enc != enc2 && enc != ascii8bit) {
|
||||||
str = rb_str_conv_enc(str, enc2, enc);
|
str = rb_str_conv_enc(str, enc2, enc);
|
||||||
@ -1439,7 +1442,8 @@ strio_truncate(VALUE self, VALUE len)
|
|||||||
static VALUE
|
static VALUE
|
||||||
strio_external_encoding(VALUE self)
|
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
|
|||||||
strio_set_encoding(int argc, VALUE *argv, VALUE self)
|
strio_set_encoding(int argc, VALUE *argv, VALUE self)
|
||||||
{
|
{
|
||||||
rb_encoding* enc;
|
rb_encoding* enc;
|
||||||
VALUE str = StringIO(self)->string;
|
struct StringIO *ptr = StringIO(self);
|
||||||
VALUE ext_enc, int_enc, opt;
|
VALUE ext_enc, int_enc, opt;
|
||||||
|
|
||||||
argc = rb_scan_args(argc, argv, "11:", &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, VALUE self)
|
|||||||
else {
|
else {
|
||||||
enc = rb_to_encoding(ext_enc);
|
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;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,6 +148,13 @@ class TestStringIO < Test::Unit::TestCase
|
|||||||
f.write(s)
|
f.write(s)
|
||||||
}
|
}
|
||||||
assert_equal(Encoding::ASCII_8BIT, f.string.encoding, bug10285)
|
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
|
end
|
||||||
|
|
||||||
def test_mode_error
|
def test_mode_error
|
||||||
|
Loading…
x
Reference in New Issue
Block a user