Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion ext/gmp/gmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
55 changes: 55 additions & 0 deletions ext/gmp/tests/gh22549.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
--TEST--
GH-22549 (Assertion failure in _zendi_try_convert_scalar_to_number with compound GMP shift/pow)
--EXTENSIONS--
gmp
--FILE--
<?php
// Compound assignment aliases result and op1. A negative GMP shift/exponent
// must throw a ValueError, not clobber op1 into IS_UNDEF and abort.
$cases = [
'int ** gmp' => [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
Loading