mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-bigint: add exponent size check in mrb_bint_pow
prevent resource exhaustion when computing power with extremely large exponents (e.g., 81.pow(51742871469327219)). the check estimates the result size and raises RangeError if it would exceed 1 million bits. Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -3417,6 +3417,10 @@ mrb_bint_cmp(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
return mpz_cmp(ctx, &a, &b);
|
||||
}
|
||||
|
||||
/* Maximum bits for power result to prevent resource exhaustion */
|
||||
/* 1 million bits = ~125KB per bigint, ~300,000 decimal digits */
|
||||
#define MRB_BIGINT_POW_MAX_BITS 1000000
|
||||
|
||||
mrb_value
|
||||
mrb_bint_pow(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
{
|
||||
@@ -3432,9 +3436,22 @@ mrb_bint_pow(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
mrb_raisef(mrb, E_TYPE_ERROR, "%Y cannot be convert to integer", y);
|
||||
}
|
||||
|
||||
mrb_int exp = mrb_integer(y);
|
||||
if (exp < 0) {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "negative exponent");
|
||||
}
|
||||
|
||||
/* Check if result would be too large */
|
||||
/* result_bits ≈ base_bits * exp */
|
||||
size_t base_bits = mpz_bits(&a);
|
||||
if (base_bits == 0) base_bits = 1; /* handle 0 and 1 */
|
||||
if (exp > 0 && (size_t)exp > MRB_BIGINT_POW_MAX_BITS / base_bits) {
|
||||
mrb_raise(mrb, E_RANGE_ERROR, "exponent too large");
|
||||
}
|
||||
|
||||
mpz_t z;
|
||||
MPZ_CTX_INIT(mrb, ctx, pool);
|
||||
mpz_pow(ctx, &z, &a, mrb_integer(y));
|
||||
mpz_pow(ctx, &z, &a, exp);
|
||||
|
||||
struct RBigint *b = bint_new(ctx, &z);
|
||||
return mrb_obj_value(b);
|
||||
|
||||
Reference in New Issue
Block a user