Fix premature string collection during append

Previously, the following crashed due to use-after-free
with AArch64 Alpine Linux 3.18.3 (aarch64-linux-musl):

```ruby
str = 'a' * (32*1024*1024)
p({z: str})
```

32 MiB is the default for `GC_MALLOC_LIMIT_MAX`, and the crash
could be dodged by setting `RUBY_GC_MALLOC_LIMIT_MAX` to large values.
Under a debugger, one can see the `str2` of rb_str_buf_append()
getting prematurely collected while str_buf_cat4() allocates capacity.

Add GC guards so the buffer of `str2` lives across the GC run
initiated in str_buf_cat4().

[Bug #19792]
This commit is contained in:
Alan Wu 2023-08-23 17:37:16 -04:00
parent d7f1ea7155
commit 2214bcb70d

View File

@ -3243,6 +3243,7 @@ rb_str_buf_append(VALUE str, VALUE str2)
case ENC_CODERANGE_7BIT:
// If RHS is 7bit we can do simple concatenation
str_buf_cat4(str, RSTRING_PTR(str2), RSTRING_LEN(str2), true);
RB_GC_GUARD(str2);
return str;
case ENC_CODERANGE_VALID:
// If RHS is valid, we can do simple concatenation if encodings are the same
@ -3252,6 +3253,7 @@ rb_str_buf_append(VALUE str, VALUE str2)
if (UNLIKELY(str_cr != ENC_CODERANGE_VALID)) {
ENC_CODERANGE_SET(str, RB_ENC_CODERANGE_AND(str_cr, str2_cr));
}
RB_GC_GUARD(str2);
return str;
}
}