From a5e25393b821badeabea17bdd365f1148cec6764 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 25 Oct 2025 07:57:44 +0900 Subject: [PATCH] mruby-bigint: fix memory leak in mpz_mod_2exp by clearing before reinit mpz_mod_2exp() was reinitializing its output parameter without clearing existing heap memory. When the parameter contained heap allocations from pool->heap transitions in mpz_mul()->mpz_realloc(), reinitializing would overwrite the pointer and leak memory. Added mpz_clear() before each mpz_init() or mpz_init_heap() call to properly free existing heap memory. Co-authored-by: Claude --- mrbgems/mruby-bigint/core/bigint.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mrbgems/mruby-bigint/core/bigint.c b/mrbgems/mruby-bigint/core/bigint.c index 71dadf317..5c9f05901 100644 --- a/mrbgems/mruby-bigint/core/bigint.c +++ b/mrbgems/mruby-bigint/core/bigint.c @@ -2117,6 +2117,7 @@ static void mpz_mod_2exp(mpz_ctx_t *ctx, mpz_t *z, mpz_t *x, mrb_int e) { if (e <= 0) { + mpz_clear(ctx, z); mpz_init(ctx, z); zero(z); return; @@ -2128,6 +2129,7 @@ mpz_mod_2exp(mpz_ctx_t *ctx, mpz_t *z, mpz_t *x, mrb_int e) if (eint >= sz) { /* x < 2^e, so x mod 2^e = x */ + mpz_clear(ctx, z); mpz_init_heap(ctx, z, x->sz); mpz_set(ctx, z, x); return; @@ -2135,6 +2137,7 @@ mpz_mod_2exp(mpz_ctx_t *ctx, mpz_t *z, mpz_t *x, mrb_int e) /* Need to mask off high bits */ size_t result_sz = eint + (bs > 0 ? 1 : 0); + mpz_clear(ctx, z); mpz_init_heap(ctx, z, result_sz); mpz_realloc(ctx, z, result_sz); z->sn = x->sn; @@ -2675,6 +2678,9 @@ mpz_barrett_reduce(mpz_ctx_t *ctx, mpz_t *r, mpz_t *x, mpz_t *m, mpz_t *mu) return; } + /* Save pool state for proper cleanup of temporary allocations */ + size_t pool_state = pool_save(ctx); + mpz_t q1, q2, q3, r1, r2; /* Conservative size estimates for Barrett reduction temporaries */ size_t q_size = x->sz + mu->sz + 1; /* For multiplication results */ @@ -2726,11 +2732,15 @@ mpz_barrett_reduce(mpz_ctx_t *ctx, mpz_t *r, mpz_t *x, mpz_t *m, mpz_t *mu) mpz_sub(ctx, r, r, m); } + /* Cleanup temporaries */ mpz_clear(ctx, &q1); mpz_clear(ctx, &q2); mpz_clear(ctx, &q3); mpz_clear(ctx, &r1); mpz_clear(ctx, &r2); + + /* Restore pool state to free any temporary pool allocations */ + pool_restore(ctx, pool_state); } static void