diff --git a/NEWS b/NEWS index e5dd4913e580..72f8e3a8c286 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,10 @@ PHP NEWS . Fixed bug GH-11020 (exif_read_data() emits a spurious "Illegal IFD size" warning when an IFD is not followed by a next-IFD offset). (Eyüp Can Akman) +- GMP: + . Fixed bug GH-22549 (Assertion failure / UB on a compound GMP power or shift + assignment with a negative exponent). (iliaal) + - Intl: . Fixed NumberFormatter::parse() and NumberFormatter::parseCurrency() to reject offset values outside the 32-bit range instead of silently diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index ef06d0fda30c..59209c4e1be3 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -361,7 +361,6 @@ static zend_result shift_operator_helper(gmp_binary_ui_op_t op, zval *return_val zend_ce_value_error, "%s must be between 0 and %lu", opcode == ZEND_POW ? "Exponent" : "Shift", ULONG_MAX ); - ZVAL_UNDEF(return_value); return FAILURE; } else { mpz_ptr gmpnum_op, gmpnum_result; diff --git a/ext/gmp/tests/gh22549.phpt b/ext/gmp/tests/gh22549.phpt new file mode 100644 index 000000000000..82a66901bd09 --- /dev/null +++ b/ext/gmp/tests/gh22549.phpt @@ -0,0 +1,55 @@ +--TEST-- +GH-22549 (Assertion failure in _zendi_try_convert_scalar_to_number with compound GMP shift/pow) +--EXTENSIONS-- +gmp +--FILE-- + [2, fn(&$x) => $x **= gmp_init(-5)], + 'gmp ** gmp' => [gmp_init(2), fn(&$x) => $x **= gmp_init(-5)], + 'array ** gmp' => [[0], fn(&$x) => $x **= gmp_init(-5)], + 'int << gmp' => [8, fn(&$x) => $x <<= gmp_init(-2)], + 'int >> gmp' => [8, fn(&$x) => $x >>= gmp_init(-2)], + 'gmp << gmp' => [gmp_init(8), fn(&$x) => $x <<= gmp_init(-2)], +]; + +foreach ($cases as $label => [$x, $op]) { + try { + $op($x); + echo "$label: no exception\n"; + } catch (\Throwable $e) { + echo "$label: ", $e::class, ": ", $e->getMessage(), "\n"; + } + var_dump($x); +} + +// Valid operations must still succeed (guard against an over-broad regression). +$p = 2; $p **= gmp_init(3); echo "valid pow: ", gmp_strval($p), "\n"; +$s = 1; $s <<= gmp_init(4); echo "valid shift: ", gmp_strval($s), "\n"; +?> +--EXPECTF-- +int ** gmp: ValueError: Exponent must be between 0 and %d +int(2) +gmp ** gmp: ValueError: Exponent must be between 0 and %d +object(GMP)#%d (1) { + ["num"]=> + string(1) "2" +} +array ** gmp: ValueError: Exponent must be between 0 and %d +array(1) { + [0]=> + int(0) +} +int << gmp: ValueError: Shift must be between 0 and %d +int(8) +int >> gmp: ValueError: Shift must be between 0 and %d +int(8) +gmp << gmp: ValueError: Shift must be between 0 and %d +object(GMP)#%d (1) { + ["num"]=> + string(1) "8" +} +valid pow: 8 +valid shift: 16