Don't modify fstrings in rb_str_tmp_frozen_no_embed_acquire (#15104)

[Bug #21671]
This commit is contained in:
John Hawthorn 2025-11-07 19:44:56 -08:00 committed by GitHub
parent a7eba54539
commit 9e426489f0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 12 additions and 1 deletions

2
gc.c
View File

@ -1245,6 +1245,8 @@ rb_gc_obj_free_vm_weak_references(VALUE obj)
switch (BUILTIN_TYPE(obj)) {
case T_STRING:
if (FL_TEST(obj, RSTRING_FSTR)) {
RUBY_ASSERT(!FL_TEST(obj, STR_SHARED));
st_data_t fstr = (st_data_t)obj;
st_delete(rb_vm_fstring_table(), &fstr, NULL);
RB_DEBUG_COUNTER_INC(obj_str_fstr);

View File

@ -1500,7 +1500,7 @@ rb_str_tmp_frozen_no_embed_acquire(VALUE orig)
* allocated. If the string is shared then the shared root must be
* embedded, so we want to create a copy. If the string is a shared root
* then it must be embedded, so we want to create a copy. */
if (STR_EMBED_P(orig) || FL_TEST_RAW(orig, STR_SHARED | STR_SHARED_ROOT)) {
if (STR_EMBED_P(orig) || FL_TEST_RAW(orig, STR_SHARED | STR_SHARED_ROOT | RSTRING_FSTR)) {
RSTRING(str)->as.heap.ptr = rb_xmalloc_mul_add_mul(sizeof(char), capa, sizeof(char), TERM_LEN(orig));
memcpy(RSTRING(str)->as.heap.ptr, RSTRING_PTR(orig), capa);
}

View File

@ -3438,6 +3438,15 @@ CODE
assert_equal(false, str.frozen?)
end
def test_uminus_no_embed_gc
pad = "a"*2048
("aa".."zz").each do |c|
fstr = -(c + pad).freeze
File.open(IO::NULL, "w").write(fstr)
end
GC.start
end
def test_ord
assert_equal(97, S("a").ord)
assert_equal(97, S("abc").ord)