From 3f2611ebcd6c4d184a8a54f5146d5f409b3f95c7 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 19 Nov 2025 08:54:30 +0900 Subject: [PATCH] bigint.c: fix buffer overflow in uadd with mismatched operand sizes fix out-of-bounds read when adding bigints of different sizes. the unrolled loop accessed both operands up to the size of x without checking if y had enough limbs. when y->sz < x->sz, this caused reads beyond y's allocation. now use min(x->sz, y->sz) for the overlap region and handle remaining limbs from the larger operand separately. Co-authored-by: Claude --- mrbgems/mruby-bigint/core/bigint.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/mrbgems/mruby-bigint/core/bigint.c b/mrbgems/mruby-bigint/core/bigint.c index bb5fc918f..331c30169 100644 --- a/mrbgems/mruby-bigint/core/bigint.c +++ b/mrbgems/mruby-bigint/core/bigint.c @@ -354,10 +354,11 @@ uadd(mpz_t *z, mpz_t *x, mpz_t *y) /* Core multi-limb addition with carry propagation */ mp_dbl_limb c = 0; size_t i; + size_t min_sz = (x->sz < y->sz) ? x->sz : y->sz; /* Add overlapping limbs from both operands */ /* 4x unrolled loop for better performance */ - for (i = 0; i + 4 <= x->sz; i += 4) { + for (i = 0; i + 4 <= min_sz; i += 4) { c += (mp_dbl_limb)y->p[i] + (mp_dbl_limb)x->p[i]; z->p[i] = LOW(c); c >>= DIG_SIZE; @@ -375,13 +376,20 @@ uadd(mpz_t *z, mpz_t *x, mpz_t *y) c >>= DIG_SIZE; } - /* Handle remaining elements */ - for (; i < x->sz; i++) { + /* Handle remaining elements in overlap */ + for (; i < min_sz; i++) { c += (mp_dbl_limb)y->p[i] + (mp_dbl_limb)x->p[i]; z->p[i] = LOW(c); c >>= DIG_SIZE; } + /* Add remaining limbs from x if it's larger */ + for (; i < x->sz; i++) { + c += x->p[i]; + z->p[i] = LOW(c); + c >>= DIG_SIZE; + } + /* Add remaining limbs from larger operand */ /* 4x unrolled loop for better performance */ for (; i + 4 <= y->sz; i += 4) {