зеркало из https://github.com/github/ruby.git
merge revision(s) bd786e78969f9d4a8699376ceafe10934b6ad533: [Backport #19084]
Fix mutation on shared strings. (#7837) --- io_buffer.c | 19 ++++++++++++------- test/ruby/test_io_buffer.rb | 4 ---- 2 files changed, 12 insertions(+), 11 deletions(-)
This commit is contained in:
Родитель
5ad2390b55
Коммит
c911cbd6c3
25
io_buffer.c
25
io_buffer.c
|
@ -299,20 +299,22 @@ rb_io_buffer_type_allocate(VALUE self)
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE io_buffer_for_make_instance(VALUE klass, VALUE string, enum rb_io_buffer_flags flags)
|
||||||
io_buffer_for_make_instance(VALUE klass, VALUE string)
|
|
||||||
{
|
{
|
||||||
VALUE instance = rb_io_buffer_type_allocate(klass);
|
VALUE instance = rb_io_buffer_type_allocate(klass);
|
||||||
|
|
||||||
struct rb_io_buffer *data = NULL;
|
struct rb_io_buffer *buffer = NULL;
|
||||||
TypedData_Get_Struct(instance, struct rb_io_buffer, &rb_io_buffer_type, data);
|
TypedData_Get_Struct(instance, struct rb_io_buffer, &rb_io_buffer_type, buffer);
|
||||||
|
|
||||||
enum rb_io_buffer_flags flags = RB_IO_BUFFER_EXTERNAL;
|
flags |= RB_IO_BUFFER_EXTERNAL;
|
||||||
|
|
||||||
if (RB_OBJ_FROZEN(string))
|
if (RB_OBJ_FROZEN(string))
|
||||||
flags |= RB_IO_BUFFER_READONLY;
|
flags |= RB_IO_BUFFER_READONLY;
|
||||||
|
|
||||||
io_buffer_initialize(data, RSTRING_PTR(string), RSTRING_LEN(string), flags, string);
|
if (!(flags & RB_IO_BUFFER_READONLY))
|
||||||
|
rb_str_modify(string);
|
||||||
|
|
||||||
|
io_buffer_initialize(buffer, RSTRING_PTR(string), RSTRING_LEN(string), flags, string);
|
||||||
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
@ -321,6 +323,7 @@ struct io_buffer_for_yield_instance_arguments {
|
||||||
VALUE klass;
|
VALUE klass;
|
||||||
VALUE string;
|
VALUE string;
|
||||||
VALUE instance;
|
VALUE instance;
|
||||||
|
enum rb_io_buffer_flags flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
@ -328,9 +331,9 @@ io_buffer_for_yield_instance(VALUE _arguments)
|
||||||
{
|
{
|
||||||
struct io_buffer_for_yield_instance_arguments *arguments = (struct io_buffer_for_yield_instance_arguments *)_arguments;
|
struct io_buffer_for_yield_instance_arguments *arguments = (struct io_buffer_for_yield_instance_arguments *)_arguments;
|
||||||
|
|
||||||
rb_str_locktmp(arguments->string);
|
arguments->instance = io_buffer_for_make_instance(arguments->klass, arguments->string, arguments->flags);
|
||||||
|
|
||||||
arguments->instance = io_buffer_for_make_instance(arguments->klass, arguments->string);
|
rb_str_locktmp(arguments->string);
|
||||||
|
|
||||||
return rb_yield(arguments->instance);
|
return rb_yield(arguments->instance);
|
||||||
}
|
}
|
||||||
|
@ -364,7 +367,8 @@ io_buffer_for_yield_instance_ensure(VALUE _arguments)
|
||||||
* collector, the source string will be locked and cannot be modified.
|
* collector, the source string will be locked and cannot be modified.
|
||||||
*
|
*
|
||||||
* If the string is frozen, it will create a read-only buffer which cannot be
|
* If the string is frozen, it will create a read-only buffer which cannot be
|
||||||
* modified.
|
* modified. If the string is shared, it may trigger a copy-on-write when
|
||||||
|
* using the block form.
|
||||||
*
|
*
|
||||||
* string = 'test'
|
* string = 'test'
|
||||||
* buffer = IO::Buffer.for(string)
|
* buffer = IO::Buffer.for(string)
|
||||||
|
@ -396,6 +400,7 @@ rb_io_buffer_type_for(VALUE klass, VALUE string)
|
||||||
.klass = klass,
|
.klass = klass,
|
||||||
.string = string,
|
.string = string,
|
||||||
.instance = Qnil,
|
.instance = Qnil,
|
||||||
|
.flags = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
return rb_ensure(io_buffer_for_yield_instance, (VALUE)&arguments, io_buffer_for_yield_instance_ensure, (VALUE)&arguments);
|
return rb_ensure(io_buffer_for_yield_instance, (VALUE)&arguments, io_buffer_for_yield_instance_ensure, (VALUE)&arguments);
|
||||||
|
@ -403,7 +408,7 @@ rb_io_buffer_type_for(VALUE klass, VALUE string)
|
||||||
else {
|
else {
|
||||||
// This internally returns the source string if it's already frozen.
|
// This internally returns the source string if it's already frozen.
|
||||||
string = rb_str_tmp_frozen_acquire(string);
|
string = rb_str_tmp_frozen_acquire(string);
|
||||||
return io_buffer_for_make_instance(klass, string);
|
return io_buffer_for_make_instance(klass, string, RB_IO_BUFFER_READONLY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -348,10 +348,6 @@ class TestIOBuffer < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_read
|
def test_read
|
||||||
# This is currently a bug in IO:Buffer [#19084] which affects extended
|
|
||||||
# strings. On 32 bit machines, the example below becomes extended, so
|
|
||||||
# we omit this test until the bug is fixed.
|
|
||||||
omit if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
|
|
||||||
io = Tempfile.new
|
io = Tempfile.new
|
||||||
io.write("Hello World")
|
io.write("Hello World")
|
||||||
io.seek(0)
|
io.seek(0)
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
|
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
|
||||||
#define RUBY_VERSION_TEENY 2
|
#define RUBY_VERSION_TEENY 2
|
||||||
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
|
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
|
||||||
#define RUBY_PATCHLEVEL 70
|
#define RUBY_PATCHLEVEL 71
|
||||||
|
|
||||||
#include "ruby/version.h"
|
#include "ruby/version.h"
|
||||||
#include "ruby/internal/abi.h"
|
#include "ruby/internal/abi.h"
|
||||||
|
|
Загрузка…
Ссылка в новой задаче