From dc5566e5603be4ed57fb94e91c24e9adce286c87 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 20 Nov 2024 11:27:54 +0900 Subject: [PATCH] mruby-bigint (int_fit_limb_p): fix the logic to check mrb_int size `int_fit_limb_p()` checks if `mrb_int` fits in `mp_limb`. Previous logic did not work well with negative integers. --- mrbgems/mruby-bigint/core/bigint.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/mrbgems/mruby-bigint/core/bigint.c b/mrbgems/mruby-bigint/core/bigint.c index 4d0dec8b0..7b2698c14 100644 --- a/mrbgems/mruby-bigint/core/bigint.c +++ b/mrbgems/mruby-bigint/core/bigint.c @@ -1477,6 +1477,28 @@ mrb_bint_as_uint64(mrb_state *mrb, mrb_value x) return u; } +static mrb_bool +int_fit_limb_p(mrb_int i) +{ +#ifdef MRB_INT64 +#if DIG_SIZE == 32 + // if mp_limb is int32_t + return (i >= INT32_MIN && i <= INT32_MAX); +#else /* if DIG_SIZE == 16 */ + // if mp_limb is int16_t + return (i >= INT16_MIN && i <= INT16_MAX); +#endif +#else /* MRB_INT32 */ +#if DIG_SIZE == 32 + // if mp_limb is also int32_t, it always fits + return true; +#else /* if DIG_SIZE == 16 */ + // if mp_limb is int16_t + return (i >= INT16_MIN && i <= INT16_MAX); +#endif +#endif +} + /* unnormalize version of mrb_bint_add */ mrb_value mrb_bint_add_n(mrb_state *mrb, mrb_value x, mrb_value y) @@ -1486,7 +1508,7 @@ mrb_bint_add_n(mrb_state *mrb, mrb_value x, mrb_value y) bint_as_mpz(RBIGINT(x), &a); if (mrb_integer_p(y)) { mrb_int i = mrb_integer(y); - if (LOW(i) == i) { + if (int_fit_limb_p(i)) { mpz_init_set(mrb, &z, &a); if ((i > 0) ^ (z.sn > 0)) { mpz_sub_int(mrb, &z, i); @@ -1529,7 +1551,7 @@ mrb_bint_sub_n(mrb_state *mrb, mrb_value x, mrb_value y) bint_as_mpz(RBIGINT(x), &a); if (mrb_integer_p(y)) { mrb_int i = mrb_integer(y); - if (LOW(i) == i) { + if (int_fit_limb_p(i)) { mpz_init_set(mrb, &z, &a); if ((i > 0) ^ (z.sn > 0)) { mpz_add_int(mrb, &z, i);