Skip to content

Commit

Permalink
ext/gmp: gmp_pow fix FPE with large values.
Browse files Browse the repository at this point in the history
even without sanitizers, it is reproducible but with the following

```
<?php
$g = gmp_init(256);
var_dump(gmp_pow($g, PHP_INT_MAX));
```

we get this

```
AddressSanitizer:DEADLYSIGNAL
=================================================================
==286922==ERROR: AddressSanitizer: FPE on unknown address 0x03e8000460ca (pc 0x7faf6c69de5c bp 0x400000000000004 sp 0x7ffe9843c740 T0)
    #0 0x7faf6c69de5c in __pthread_kill_implementation nptl/pthread_kill.c:44
    #1 0x7faf6c649c81 in __GI_raise ../sysdeps/posix/raise.c:26
    #2 0x7faf6db9386c in __gmp_exception (/lib/x86_64-linux-gnu/libgmp.so.10+0xd86c) (BuildId: 1af68a49fe041a5bb48a2915c3d47541f713bb38)
    #3 0x7faf6db938d3 in __gmp_overflow_in_mpz (/lib/x86_64-linux-gnu/libgmp.so.10+0xd8d3) (BuildId: 1af68a49fe041a5bb48a2915c3d47541f713bb38)
    #4 0x7faf6dbac95c in __gmpz_realloc (/lib/x86_64-linux-gnu/libgmp.so.10+0x2695c) (BuildId: 1af68a49fe041a5bb48a2915c3d47541f713bb38)
    #5 0x7faf6dba9038 in __gmpz_n_pow_ui (/lib/x86_64-linux-gnu/libgmp.so.10+0x23038) (BuildId: 1af68a49fe041a5bb48a2915c3d47541f713bb38)
    #6 0x5565ae1ccd9f in zif_gmp_pow /home/dcarlier/Contribs/php-src/ext/gmp/gmp.c:1286
    #7 0x5565aee96ea9 in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER /home/dcarlier/Contribs/php-src/Zend/zend_vm_execute.h:1312
    #8 0x5565af144320 in execute_ex /home/dcarlier/Contribs/php-src/Zend/zend_vm_execute.h:56075
    #9 0x5565af160f07 in zend_execute /home/dcarlier/Contribs/php-src/Zend/zend_vm_execute.h:60439
    #10 0x5565aed6fafe in zend_execute_scripts /home/dcarlier/Contribs/php-src/Zend/zend.c:1842
    #11 0x5565aeae70a8 in php_execute_script /home/dcarlier/Contribs/php-src/main/main.c:2578
    #12 0x5565af532f4e in do_cli /home/dcarlier/Contribs/php-src/sapi/cli/php_cli.c:964
    #13 0x5565af535877 in main /home/dcarlier/Contribs/php-src/sapi/cli/php_cli.c:1334
    #14 0x7faf6c633d67 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #15 0x7faf6c633e24 in __libc_start_main_impl ../csu/libc-start.c:360
    #16 0x5565adc04040 in _start (/home/dcarlier/Contribs/php-src/sapi/cli/php+0x2604040) (BuildId: 949049955bdf8b7197390b1978a1dfc3ef6fdf38)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: FPE nptl/pthread_kill.c:44 in __pthread_kill_implementation
==286922==ABORTING
```
  • Loading branch information
devnexen committed Oct 13, 2024
1 parent 84a8fea commit d70b781
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 2 deletions.
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ PHP NEWS
. Fixed bug GH-16334 (imageaffine overflow on matrix elements).
(David Carlier)

- GMP:
. Fixed floating point exception bug with gmp_pow when using
large exposant values. (David Carlier).

- MBstring:
. Fixed bug GH-16361 (mb_substr overflow on start/length arguments).
(David Carlier)
Expand Down
29 changes: 27 additions & 2 deletions ext/gmp/gmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1278,12 +1278,37 @@ ZEND_FUNCTION(gmp_pow)

if (Z_TYPE_P(base_arg) == IS_LONG && Z_LVAL_P(base_arg) >= 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);
}
}
Expand Down
20 changes: 20 additions & 0 deletions ext/gmp/tests/gmp_pow_fpe.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
--TEST--
gmp_pow() floating point exception
--EXTENSIONS--
gmp
--FILE--
<?php
$g = gmp_init(256);

var_dump(gmp_pow($g, PHP_INT_MAX));
var_dump(gmp_pow(256, PHP_INT_MAX));
?>
--EXPECTF--
object(GMP)#2 (1) {
["num"]=>
string(%d) "%s"
}
object(GMP)#2 (1) {
["num"]=>
string(%d) "%s"
}

0 comments on commit d70b781

Please sign in to comment.