From c28223ac5bbd18306f8d8677d95a071c1f7129a6 Mon Sep 17 00:00:00 2001 From: dearblue Date: Sun, 26 Oct 2025 21:02:20 +0900 Subject: [PATCH] Fix integer overflow in allocation size calculation Passing a large integer value as the first argument to `Array#ary_combination_init` could cause an incorrect memory allocation due to integer overflow. This would result in an invalid write during the subsequent zero-fill of the memory. To resolve the issue, it has been replaced with `mrb_calloc()`. However, since the current `mrb_calloc()` returns `NULL` due to overflow, it has been modified to raise an exception as a clear error. --- mrbgems/mruby-array-ext/src/array.c | 10 ++++++---- src/gc.c | 8 +++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/mrbgems/mruby-array-ext/src/array.c b/mrbgems/mruby-array-ext/src/array.c index 426d95bb3..16c9fde95 100644 --- a/mrbgems/mruby-array-ext/src/array.c +++ b/mrbgems/mruby-array-ext/src/array.c @@ -1315,6 +1315,11 @@ ary_combination_init(mrb_state *mrb, mrb_value self) mrb_bool permutation; mrb_get_args(mrb, "ib", &n, &permutation); +#if MRB_INT_MAX > SIZE_MAX + if (n > SIZE_MAX) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "number too large"); + } +#endif struct mrb_combination_state *state = (struct mrb_combination_state*)mrb_malloc(mrb, sizeof(*state)); state->n = n; @@ -1323,10 +1328,7 @@ ary_combination_init(mrb_state *mrb, mrb_value self) state->finished = (n <= 0 && n != 0); if (n > 0) { - state->indices = (mrb_int*)mrb_malloc(mrb, sizeof(mrb_int) * n); - for (mrb_int i = 0; i < n; i++) { - state->indices[i] = 0; - } + state->indices = (mrb_int*)mrb_calloc(mrb, n, sizeof(mrb_int)); } else { state->indices = NULL; diff --git a/src/gc.c b/src/gc.c index 825d54600..ef91432af 100644 --- a/src/gc.c +++ b/src/gc.c @@ -243,15 +243,17 @@ mrb_calloc(mrb_state *mrb, size_t nelem, size_t len) { void *p; - if (nelem > 0 && len > 0 && - nelem <= SIZE_MAX / len) { + if (nelem == 0 || len == 0) { + p = NULL; + } + else if (nelem <= SIZE_MAX / len) { size_t size = nelem * len; p = mrb_malloc(mrb, size); memset(p, 0, size); } else { - p = NULL; + mrb_raise(mrb, E_ARGUMENT_ERROR, "memory allocation overflow"); } return p;