From d70b7811b0248a36b06d70a04e350801a1fede8e Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 12 Oct 2024 07:14:56 +0100 Subject: [PATCH] ext/gmp: gmp_pow fix FPE with large values. even without sanitizers, it is reproducible but with the following ``` = 0) { INIT_GMP_RETVAL(gmpnum_result); - mpz_ui_pow_ui(gmpnum_result, Z_LVAL_P(base_arg), exp); + if (exp >= INT_MAX) { + mpz_t base_num, exp_num, mod; + mpz_init(base_num); + mpz_init(exp_num); + mpz_init(mod); + mpz_set_si(base_num, Z_LVAL_P(base_arg)); + mpz_set_si(exp_num, exp); + mpz_set_ui(mod, UINT_MAX); + mpz_powm(gmpnum_result, base_num, exp_num, mod); + mpz_clear(mod); + mpz_clear(exp_num); + mpz_clear(base_num); + } else { + mpz_ui_pow_ui(gmpnum_result, Z_LVAL_P(base_arg), exp); + } } else { mpz_ptr gmpnum_base; FETCH_GMP_ZVAL(gmpnum_base, base_arg, temp_base, 1); INIT_GMP_RETVAL(gmpnum_result); - mpz_pow_ui(gmpnum_result, gmpnum_base, exp); + if (exp >= INT_MAX) { + mpz_t exp_num, mod; + mpz_init(exp_num); + mpz_init(mod); + mpz_set_si(exp_num, exp); + mpz_set_ui(mod, UINT_MAX); + mpz_powm(gmpnum_result, gmpnum_base, exp_num, mod); + mpz_clear(mod); + mpz_clear(exp_num); + } else { + mpz_pow_ui(gmpnum_result, gmpnum_base, exp); + } FREE_GMP_TEMP(temp_base); } } diff --git a/ext/gmp/tests/gmp_pow_fpe.phpt b/ext/gmp/tests/gmp_pow_fpe.phpt new file mode 100644 index 0000000000000..d564853799c8d --- /dev/null +++ b/ext/gmp/tests/gmp_pow_fpe.phpt @@ -0,0 +1,20 @@ +--TEST-- +gmp_pow() floating point exception +--EXTENSIONS-- +gmp +--FILE-- + +--EXPECTF-- +object(GMP)#2 (1) { + ["num"]=> + string(%d) "%s" +} +object(GMP)#2 (1) { + ["num"]=> + string(%d) "%s" +}