[ruby/stringio] Make sure shared buffer is copied on mutation

(https://github.com/ruby/stringio/pull/117)

We need to ensure shared buffers are made independent on mutation.
Otherwise we could end up mutating unrelated string buffers.

---------

https://github.com/ruby/stringio/commit/5101cfb030

Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
Co-authored-by: Aaron Patterson <aaron.patterson@gmail.com>
Co-authored-by: Sutou Kouhei <kou@cozmixng.org>
This commit is contained in:
Aaron Patterson 2025-02-19 16:18:02 -08:00 committed by git
parent c515da3d74
commit a27758ad4e
2 changed files with 19 additions and 0 deletions

View File

@ -180,6 +180,7 @@ check_modifiable(struct StringIO *ptr)
else if (OBJ_FROZEN_RAW(ptr->string)) {
rb_raise(rb_eIOError, "not modifiable string");
}
rb_str_modify(ptr->string);
}
static VALUE

View File

@ -14,6 +14,24 @@ class TestStringIO < Test::Unit::TestCase
include TestEOF::Seek
def test_do_not_mutate_shared_buffers
# Ensure we have two strings that are not embedded but have the same shared
# string reference.
#
# In this case, we must use eval because we need two strings literals that
# are long enough they cannot be embedded, but also contain the same bytes.
a = eval(("x" * 1024).dump)
b = eval(("x" * 1024).dump)
s = StringIO.new(b)
s.getc
s.ungetc '#'
# We mutated b, so a should not be mutated
assert_equal("x", a[0])
end
def test_version
assert_kind_of(String, StringIO::VERSION)
end