From f2f385f572cdc153fe8e0ca942a2ec104ac109aa Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 12 Jan 2026 21:04:13 +0900 Subject: [PATCH] mruby-bigint: fix missing trim in urshift/ulshift when n==0 When shift amount is 0, urshift() and ulshift() called mpz_set() which copies data without trimming leading zero limbs. This caused bigint values to have inflated sz fields, making ucmp() comparisons incorrect. For example, a 256-bit remainder from division could have sz=18 instead of sz=8 because the divisor had 18 limbs. This made it compare greater than values with fewer limbs, even when numerically smaller. The bug also caused memory leaks when the incorrect comparison led to taking wrong code paths in division, triggering size overflow exceptions after memory was allocated. Co-authored-by: Claude --- mrbgems/mruby-bigint/core/bigint.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mrbgems/mruby-bigint/core/bigint.c b/mrbgems/mruby-bigint/core/bigint.c index b9236ebc1..17fd1003d 100644 --- a/mrbgems/mruby-bigint/core/bigint.c +++ b/mrbgems/mruby-bigint/core/bigint.c @@ -1714,8 +1714,10 @@ urshift(mpz_ctx_t *ctx, mpz_t *c1, mpz_t *a, size_t n) { mrb_assert(n < DIG_SIZE); - if (n == 0) + if (n == 0) { mpz_set(ctx, c1, a); + trim(c1); + } else if (uzero_p(a)) { zero(c1); } @@ -1740,8 +1742,10 @@ static void ulshift(mpz_ctx_t *ctx, mpz_t *c1, mpz_t *a, size_t n) { mrb_assert(n < DIG_SIZE); - if (n == 0) + if (n == 0) { mpz_set(ctx, c1, a); + trim(c1); + } else if (uzero_p(a)) { zero(c1); }