Merge branch 'PHP-8.0'

* PHP-8.0:
  Fix bug #81119
This commit is contained in:
Nikita Popov 2021-06-10 14:48:06 +02:00
commit d43bc343ab
4 changed files with 65 additions and 31 deletions

View file

@ -175,7 +175,7 @@ if (IS_GMP(zval)) { \
static void gmp_strval(zval *result, mpz_t gmpnum, int base);
static zend_result convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, uint32_t arg_pos);
static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg);
static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg, bool is_operator);
/*
* The gmp_*_op functions provide an implementation for several common types
@ -194,7 +194,7 @@ typedef void (*gmp_binary_ui_op_t)(mpz_ptr, mpz_srcptr, gmp_ulong);
typedef void (*gmp_binary_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr);
typedef gmp_ulong (*gmp_binary_ui_op2_t)(mpz_ptr, mpz_ptr, mpz_srcptr, gmp_ulong);
static inline void gmp_zval_binary_ui_op(zval *return_value, zval *a_arg, zval *b_arg, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, int check_b_zero);
static inline void gmp_zval_binary_ui_op(zval *return_value, zval *a_arg, zval *b_arg, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, bool check_b_zero, bool is_operator);
static inline void gmp_zval_binary_ui_op2(zval *return_value, zval *a_arg, zval *b_arg, gmp_binary_op2_t gmp_op, gmp_binary_ui_op2_t gmp_ui_op, int check_b_zero);
static inline void gmp_zval_unary_op(zval *return_value, zval *a_arg, gmp_unary_op_t gmp_op);
@ -350,11 +350,10 @@ static void shift_operator_helper(gmp_binary_ui_op_t op, zval *return_value, zva
}
}
#define DO_BINARY_UI_OP_EX(op, uop, check_b_zero) \
gmp_zval_binary_ui_op( \
result, op1, op2, op, uop, check_b_zero \
); \
if (UNEXPECTED(EG(exception))) { return FAILURE; } \
#define DO_BINARY_UI_OP_EX(op, uop, check_b_zero) \
gmp_zval_binary_ui_op( \
result, op1, op2, op, uop, check_b_zero, /* is_operator */ true); \
if (UNEXPECTED(EG(exception))) { return FAILURE; } \
return SUCCESS;
#define DO_BINARY_UI_OP(op) DO_BINARY_UI_OP_EX(op, op ## _ui, 0)
@ -428,7 +427,7 @@ static int gmp_compare(zval *op1, zval *op2) /* {{{ */
{
zval result;
gmp_cmp(&result, op1, op2);
gmp_cmp(&result, op1, op2, /* is_operator */ true);
/* An error/exception occurs if one of the operands is not a numeric string
* or an object which is different from GMP */
@ -614,13 +613,11 @@ static zend_result convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, ui
ret = mpz_set_str(gmpnumber, (skip_lead ? &numstr[2] : numstr), (int) base);
if (-1 == ret) {
/* if unserializing */
if (arg_pos == 0) {
php_error_docref(NULL, E_WARNING,
"Cannot convert variable to GMP, it is not an integer string");
return FAILURE;
zend_value_error("Number is not an integer string");
} else {
zend_argument_value_error(arg_pos, "is not an integer string");
}
zend_argument_value_error(arg_pos, "is not an integer string");
return FAILURE;
}
@ -629,7 +626,13 @@ static zend_result convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, ui
default: {
zend_long lval;
if (!zend_parse_arg_long_slow(val, &lval, arg_pos)) {
zend_argument_type_error(arg_pos, "must be of type GMP|string|int, %s given", zend_zval_type_name(val));
if (arg_pos == 0) {
zend_type_error(
"Number must be of type GMP|string|int, %s given", zend_zval_type_name(val));
} else {
zend_argument_type_error(arg_pos,
"must be of type GMP|string|int, %s given", zend_zval_type_name(val));
}
return FAILURE;
}
@ -671,20 +674,20 @@ static void gmp_strval(zval *result, mpz_t gmpnum, int base) /* {{{ */
}
/* }}} */
static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg) /* {{{ */
static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg, bool is_operator) /* {{{ */
{
mpz_ptr gmpnum_a, gmpnum_b;
gmp_temp_t temp_a, temp_b;
bool use_si = 0;
zend_long res;
FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, is_operator ? 0 : 1);
if (Z_TYPE_P(b_arg) == IS_LONG) {
use_si = 1;
temp_b.is_used = 0;
} else {
FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a, 2);
FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a, is_operator ? 0 : 2);
}
if (use_si) {
@ -703,18 +706,18 @@ static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg) /* {{{ */
/* {{{ gmp_zval_binary_ui_op
Execute GMP binary operation.
*/
static inline void gmp_zval_binary_ui_op(zval *return_value, zval *a_arg, zval *b_arg, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, int check_b_zero)
static inline void gmp_zval_binary_ui_op(zval *return_value, zval *a_arg, zval *b_arg, gmp_binary_op_t gmp_op, gmp_binary_ui_op_t gmp_ui_op, bool check_b_zero, bool is_operator)
{
mpz_ptr gmpnum_a, gmpnum_b, gmpnum_result;
gmp_temp_t temp_a, temp_b;
FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, 1);
FETCH_GMP_ZVAL(gmpnum_a, a_arg, temp_a, is_operator ? 0 : 1);
if (gmp_ui_op && Z_TYPE_P(b_arg) == IS_LONG && Z_LVAL_P(b_arg) >= 0) {
gmpnum_b = NULL;
temp_b.is_used = 0;
} else {
FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a, 2);
FETCH_GMP_ZVAL_DEP(gmpnum_b, b_arg, temp_b, temp_a, is_operator ? 0 : 2);
}
if (check_b_zero) {
@ -811,7 +814,8 @@ static inline void _gmp_binary_ui_op(INTERNAL_FUNCTION_PARAMETERS, gmp_binary_op
RETURN_THROWS();
}
gmp_zval_binary_ui_op(return_value, a_arg, b_arg, gmp_op, gmp_ui_op, check_b_zero);
gmp_zval_binary_ui_op(
return_value, a_arg, b_arg, gmp_op, gmp_ui_op, check_b_zero, /* is_operator */ false);
}
/* }}} */
@ -1097,13 +1101,16 @@ ZEND_FUNCTION(gmp_div_r)
switch (round) {
case GMP_ROUND_ZERO:
gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_tdiv_r, gmp_mpz_tdiv_r_ui, 1);
gmp_zval_binary_ui_op(
return_value, a_arg, b_arg, mpz_tdiv_r, gmp_mpz_tdiv_r_ui, 1, /* is_operator */ false);
break;
case GMP_ROUND_PLUSINF:
gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_cdiv_r, gmp_mpz_cdiv_r_ui, 1);
gmp_zval_binary_ui_op(
return_value, a_arg, b_arg, mpz_cdiv_r, gmp_mpz_cdiv_r_ui, 1, /* is_operator */ false);
break;
case GMP_ROUND_MINUSINF:
gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_fdiv_r, gmp_mpz_fdiv_r_ui, 1);
gmp_zval_binary_ui_op(
return_value, a_arg, b_arg, mpz_fdiv_r, gmp_mpz_fdiv_r_ui, 1, /* is_operator */ false);
break;
default:
zend_argument_value_error(3, "must be one of GMP_ROUND_ZERO, GMP_ROUND_PLUSINF, or GMP_ROUND_MINUSINF");
@ -1124,13 +1131,16 @@ ZEND_FUNCTION(gmp_div_q)
switch (round) {
case GMP_ROUND_ZERO:
gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_tdiv_q, gmp_mpz_tdiv_q_ui, 1);
gmp_zval_binary_ui_op(
return_value, a_arg, b_arg, mpz_tdiv_q, gmp_mpz_tdiv_q_ui, 1, /* is_operator */ false);
break;
case GMP_ROUND_PLUSINF:
gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_cdiv_q, gmp_mpz_cdiv_q_ui, 1);
gmp_zval_binary_ui_op(
return_value, a_arg, b_arg, mpz_cdiv_q, gmp_mpz_cdiv_q_ui, 1, /* is_operator */ false);
break;
case GMP_ROUND_MINUSINF:
gmp_zval_binary_ui_op(return_value, a_arg, b_arg, mpz_fdiv_q, gmp_mpz_fdiv_q_ui, 1);
gmp_zval_binary_ui_op(
return_value, a_arg, b_arg, mpz_fdiv_q, gmp_mpz_fdiv_q_ui, 1, /* is_operator */ false);
break;
default:
zend_argument_value_error(3, "must be one of GMP_ROUND_ZERO, GMP_ROUND_PLUSINF, or GMP_ROUND_MINUSINF");
@ -1671,7 +1681,7 @@ ZEND_FUNCTION(gmp_cmp)
RETURN_THROWS();
}
gmp_cmp(return_value, a_arg, b_arg);
gmp_cmp(return_value, a_arg, b_arg, /* is_operator */ false);
}
/* }}} */

View file

@ -0,0 +1,24 @@
--TEST--
GMP operators throw errors with wrong parameter names
--FILE--
<?php
function test($f) {
try {
$f();
echo "No error?\n";
} catch (TypeError|ValueError $e) {
echo $e->getMessage(), "\n";
}
}
test(fn($WRONG_SCOPE_1 = 0, $WRONG_SCOPE_2 = 0) => gmp_init(1) < "x");
test(fn($WRONG_SCOPE_1 = 0, $WRONG_SCOPE_2 = 0) => gmp_init(1) < []);
test(fn($WRONG_SCOPE_1 = 0, $WRONG_SCOPE_2 = 0) => gmp_init(1) + "x");
test(fn($WRONG_SCOPE_1 = 0, $WRONG_SCOPE_2 = 0) => gmp_init(1) + []);
?>
--EXPECT--
Number is not an integer string
Number must be of type GMP|string|int, array given
Number is not an integer string
Number must be of type GMP|string|int, array given

View file

@ -19,5 +19,5 @@ try {
?>
--EXPECT--
ValueError: main(): Argument #2 is not an integer string
TypeError: main(): Argument #2 must be of type GMP|string|int, DateTime given
ValueError: Number is not an integer string
TypeError: Number must be of type GMP|string|int, DateTime given

View file

@ -282,7 +282,7 @@ bool(false)
bool(true)
bool(false)
bool(true)
main(): Argument #2 must be of type GMP|string|int, stdClass given
Number must be of type GMP|string|int, stdClass given
object(GMP)#4 (1) {
["num"]=>
string(2) "43"