github-actions · GitHub

mrb_str_format captured raw C pointers (p, end) into the format
string's buffer before the main loop. The %s and %p specifiers call
to_s and inspect, which can invoke Ruby code that mutates the format
string via String#replace, freeing or reallocating its buffer. The
loop then continued iterating with dangling pointers, reading freed
memory and potentially leaking adjacent heap contents into the result.
Duplicate the format string with mrb_str_dup() before the loop. This
is O(1) because mrb_str_dup shares the underlying buffer; if the
original is later mutated via String#replace, str_replace decrements
the shared refcount, leaving our duplicate's buffer intact.
Co-authored-by: Claude <noreply@anthropic.com>

gemini-code-assist[bot]

@matz

@matz

matz deleted the fix/sprintf-uaf branch

April 11, 2026 07:33

matz added a commit that referenced this pull request

Apr 12, 2026
Co-authored-by: Claude <noreply@anthropic.com>

@matz matz mentioned this pull request

Apr 12, 2026

Merged

dearblue added a commit to dearblue/mruby that referenced this pull request

Apr 13, 2026
`mrb_str_dup()` always duplicates string objects in an unfrozen state, and the class is also set.
Therefore, it can be observed and modified from the Ruby side using the `ObjectSpace.each_object` method.
By using `mrb_str_dup_frozen()`, unnecessary duplication can be avoided, and modifications to the string can also be prevented.

dearblue added a commit to dearblue/mruby that referenced this pull request

Apr 13, 2026
`mrb_str_dup()` always duplicates string objects in an unfrozen state, and the class is also set.
Therefore, it can be observed and modified from the Ruby side using the `ObjectSpace.each_object` method.
By using `mrb_str_dup_frozen()`, unnecessary duplication can be avoided, and modifications to the string can also be prevented.

Read the original on github.com ↗