mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-io: cap puts recursion depth to prevent C stack overflow
io_puts_ary recursed unconditionally on nested arrays. For cyclic arrays (a = []; a << a; puts a) or pathologically deep arrays, this caused a C stack overflow. Add a depth cap (IO_PUTS_MAX_DEPTH = 16); on overflow, write "[...]\n" and return, matching CRuby's behavior on cycles. The pattern mirrors mruby-set's MAX_NESTED_DEPTH for the same problem shape (pure C recursion not dispatched as a Ruby method). Reported by OSS-Fuzz (clusterfuzz testcase 6233530857488384). Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -992,10 +992,20 @@ io_puts_str(mrb_state *mrb, int fd, mrb_value str)
|
||||
}
|
||||
}
|
||||
|
||||
/* Maximum nesting depth for puts with arrays; guards against cyclic and
|
||||
pathologically deep arrays causing C stack overflow. */
|
||||
#define IO_PUTS_MAX_DEPTH 16
|
||||
|
||||
/* Recursive helper for puts with arrays */
|
||||
static void
|
||||
io_puts_ary(mrb_state *mrb, int fd, mrb_value ary)
|
||||
io_puts_ary(mrb_state *mrb, int fd, mrb_value ary, int depth)
|
||||
{
|
||||
if (depth >= IO_PUTS_MAX_DEPTH) {
|
||||
mrb_value mark = mrb_str_new_lit(mrb, "[...]\n");
|
||||
fd_write(mrb, fd, mark);
|
||||
return;
|
||||
}
|
||||
|
||||
mrb_int len = RARRAY_LEN(ary);
|
||||
|
||||
if (len == 0) {
|
||||
@@ -1008,7 +1018,7 @@ io_puts_ary(mrb_state *mrb, int fd, mrb_value ary)
|
||||
for (mrb_int i = 0; i < len; i++) {
|
||||
mrb_value elem = RARRAY_PTR(ary)[i];
|
||||
if (mrb_array_p(elem)) {
|
||||
io_puts_ary(mrb, fd, elem); /* Recursive call for nested arrays */
|
||||
io_puts_ary(mrb, fd, elem, depth + 1);
|
||||
}
|
||||
else {
|
||||
io_puts_str(mrb, fd, elem);
|
||||
@@ -1040,7 +1050,7 @@ io_puts(mrb_state *mrb, mrb_value io)
|
||||
for (mrb_int i = 0; i < argc; i++) {
|
||||
mrb_value arg = argv[i];
|
||||
if (mrb_array_p(arg)) {
|
||||
io_puts_ary(mrb, fd, arg);
|
||||
io_puts_ary(mrb, fd, arg, 0);
|
||||
}
|
||||
else {
|
||||
io_puts_str(mrb, fd, arg);
|
||||
|
||||
Reference in New Issue
Block a user