From 01ab2ffc29a1f2d67b2e88ec674c5288d5b97aa4 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 22 Oct 2025 14:04:14 +0900 Subject: [PATCH] mruby-io: fix buffer overflow in io#ungetc; fix #6647 io_unget_data had two issues that caused crashes with repeated ungetc: 1. Integer underflow in buffer size check: "len > MRB_IO_BUF_SIZE - buf->len" could underflow when buf->len was large, bypassing reallocation 2. Short overflow: buf->len could exceed SHRT_MAX after multiple ungetc calls, causing integer overflow when cast to short Fixed by checking buf->len + len against both MRB_IO_BUF_SIZE and SHRT_MAX before buffer operations. Co-authored-by: Claude --- mrbgems/mruby-io/src/io.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-io/src/io.c b/mrbgems/mruby-io/src/io.c index dd368b8be..0343864bd 100644 --- a/mrbgems/mruby-io/src/io.c +++ b/mrbgems/mruby-io/src/io.c @@ -1688,7 +1688,10 @@ io_unget_data(mrb_state *mrb, struct mrb_io *fptr, const char *ptr, mrb_int len) if (len > SHRT_MAX) { mrb_raise(mrb, E_ARGUMENT_ERROR, "string too long to ungetc"); } - if (len > MRB_IO_BUF_SIZE - buf->len) { + if (buf->len + len > SHRT_MAX) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "total ungetc buffer exceeds maximum size"); + } + if (buf->len + len > MRB_IO_BUF_SIZE) { fptr->buf = (struct mrb_io_buf*)mrb_realloc(mrb, buf, sizeof(struct mrb_io_buf)+buf->len+len-MRB_IO_BUF_SIZE); buf = fptr->buf; }