From 8113c0d24a1e8654aec175e1e8afd2fcdd2c583a Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 18 Nov 2025 09:33:24 +0900 Subject: [PATCH] bigint.c: fix division by zero in udiv normalization after left-shifting the divisor in udiv(), trailing zero limbs could remain, causing division by zero. added trim(&y) after ulshift() to remove zero limbs, and safety check to handle edge cases where divisor becomes zero after normalization. Co-authored-by: Claude --- mrbgems/mruby-bigint/core/bigint.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-bigint/core/bigint.c b/mrbgems/mruby-bigint/core/bigint.c index b3e49a27b..56952fa4d 100644 --- a/mrbgems/mruby-bigint/core/bigint.c +++ b/mrbgems/mruby-bigint/core/bigint.c @@ -1365,6 +1365,7 @@ udiv(mpz_ctx_t *ctx, mpz_t *qq, mpz_t *rr, mpz_t *xx, mpz_t *yy) mrb_assert(yy->sn != 0); /* divided by zero */ mrb_assert(yy->sz > 0); /* divided by zero */ + mrb_assert(!uzero_p(yy)); /* divided by zero */ /* Use new context architecture with automatic pool/heap management */ size_t pool_state = pool_save(ctx); @@ -1377,11 +1378,27 @@ udiv(mpz_ctx_t *ctx, mpz_t *qq, mpz_t *rr, mpz_t *xx, mpz_t *yy) size_t ns = lzb(yy->p[yd-1]); ulshift(ctx, &x, xx, ns); ulshift(ctx, &y, yy, ns); + trim(&y); /* Trim after shift to remove any zero limbs */ size_t xd = digits(&x); + yd = digits(&y); + + /* Handle edge case: divisor became zero after normalization */ + if (yd == 0 || y.p[yd-1] == 0) { + /* This should not happen with valid inputs, but handle gracefully */ + zero(qq); + zero(rr); + mpz_clear(ctx, &q); + mpz_clear(ctx, &x); + mpz_clear(ctx, &y); + pool_restore(ctx, pool_state); + return; + } + mpz_realloc(ctx, &q, xd-yd+1); // Quotient has xd-yd+1 digits maximum /* Core Knuth Algorithm D division loop */ mp_dbl_limb z = y.p[yd-1]; + mrb_assert(z != 0); /* Divisor high limb must be non-zero after normalization */ if (xd >= yd) { for (size_t j = xd - yd;; j--) { @@ -1501,7 +1518,7 @@ udiv(mpz_ctx_t *ctx, mpz_t *qq, mpz_t *rr, mpz_t *xx, mpz_t *yy) if (j == 0) break; } } - x.sz = yy->sz; + x.sz = yd; urshift(ctx, rr, &x, ns); trim(&q); mpz_move(ctx, qq, &q);