Skip to content

Commit 79b011b

Browse files
committed
Merge branch 'PHP-8.1' into PHP-8.2
2 parents 3675041 + 3d5df06 commit 79b011b

File tree

3 files changed

+69
-36
lines changed

3 files changed

+69
-36
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ PHP NEWS
88
. Fixed bug GH-9516 ((A&B)|D as a param should allow AB or D. Not just A).
99
(Girgias)
1010

11+
- GMP
12+
. Fixed bug GH-9308 (GMP throws the wrong error when a GMP object is passed
13+
to gmp_init()). (Girgias)
14+
1115
- Opcache:
1216
. Fixed bug GH-9259 (opcache.interned_strings_buffer setting integer
1317
overflow). (Arnaud)

ext/gmp/gmp.c

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,36 @@ ZEND_MODULE_INFO_D(gmp)
577577
}
578578
/* }}} */
579579

580+
static zend_result convert_zstr_to_gmp(mpz_t gmp_number, const zend_string *val, zend_long base, uint32_t arg_pos)
581+
{
582+
const char *num_str = ZSTR_VAL(val);
583+
bool skip_lead = false;
584+
585+
if (ZSTR_LEN(val) >= 2 && num_str[0] == '0') {
586+
if ((base == 0 || base == 16) && (num_str[1] == 'x' || num_str[1] == 'X')) {
587+
base = 16;
588+
skip_lead = true;
589+
} else if ((base == 0 || base == 8) && (num_str[1] == 'o' || num_str[1] == 'O')) {
590+
base = 8;
591+
skip_lead = true;
592+
} else if ((base == 0 || base == 2) && (num_str[1] == 'b' || num_str[1] == 'B')) {
593+
base = 2;
594+
skip_lead = true;
595+
}
596+
}
597+
598+
int gmp_ret = mpz_set_str(gmp_number, (skip_lead ? &num_str[2] : num_str), (int) base);
599+
if (-1 == gmp_ret) {
600+
if (arg_pos == 0) {
601+
zend_value_error("Number is not an integer string");
602+
} else {
603+
zend_argument_value_error(arg_pos, "is not an integer string");
604+
}
605+
return FAILURE;
606+
}
607+
608+
return SUCCESS;
609+
}
580610

581611
/* {{{ convert_to_gmp
582612
* Convert zval to be gmp number */
@@ -587,34 +617,7 @@ static zend_result convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, ui
587617
mpz_set_si(gmpnumber, Z_LVAL_P(val));
588618
return SUCCESS;
589619
case IS_STRING: {
590-
char *numstr = Z_STRVAL_P(val);
591-
bool skip_lead = 0;
592-
int ret;
593-
594-
if (Z_STRLEN_P(val) >= 2 && numstr[0] == '0') {
595-
if ((base == 0 || base == 16) && (numstr[1] == 'x' || numstr[1] == 'X')) {
596-
base = 16;
597-
skip_lead = 1;
598-
} else if ((base == 0 || base == 8) && (numstr[1] == 'o' || numstr[1] == 'O')) {
599-
base = 8;
600-
skip_lead = 1;
601-
} else if ((base == 0 || base == 2) && (numstr[1] == 'b' || numstr[1] == 'B')) {
602-
base = 2;
603-
skip_lead = 1;
604-
}
605-
}
606-
607-
ret = mpz_set_str(gmpnumber, (skip_lead ? &numstr[2] : numstr), (int) base);
608-
if (-1 == ret) {
609-
if (arg_pos == 0) {
610-
zend_value_error("Number is not an integer string");
611-
} else {
612-
zend_argument_value_error(arg_pos, "is not an integer string");
613-
}
614-
return FAILURE;
615-
}
616-
617-
return SUCCESS;
620+
return convert_zstr_to_gmp(gmpnumber, Z_STR_P(val), base, arg_pos);
618621
}
619622
default: {
620623
zend_long lval;
@@ -862,22 +865,29 @@ static inline void _gmp_unary_opl(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_opl_t
862865
/* {{{ Initializes GMP number */
863866
ZEND_FUNCTION(gmp_init)
864867
{
865-
zval *number_arg;
866-
mpz_ptr gmpnumber;
868+
mpz_ptr gmp_number;
869+
zend_string *arg_str = NULL;
870+
zend_long arg_l = 0;
867871
zend_long base = 0;
868872

869-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &number_arg, &base) == FAILURE) {
870-
RETURN_THROWS();
871-
}
873+
ZEND_PARSE_PARAMETERS_START(1, 2)
874+
Z_PARAM_STR_OR_LONG(arg_str, arg_l)
875+
Z_PARAM_OPTIONAL
876+
Z_PARAM_LONG(base)
877+
ZEND_PARSE_PARAMETERS_END();
872878

873879
if (base && (base < 2 || base > GMP_MAX_BASE)) {
874880
zend_argument_value_error(2, "must be between 2 and %d", GMP_MAX_BASE);
875881
RETURN_THROWS();
876882
}
877883

878-
INIT_GMP_RETVAL(gmpnumber);
879-
if (convert_to_gmp(gmpnumber, number_arg, base, 1) == FAILURE) {
880-
RETURN_THROWS();
884+
INIT_GMP_RETVAL(gmp_number);
885+
if (arg_str) {
886+
if (convert_zstr_to_gmp(gmp_number, arg_str, base, 1) == FAILURE) {
887+
RETURN_THROWS();
888+
}
889+
} else {
890+
mpz_set_si(gmp_number, arg_l);
881891
}
882892
}
883893
/* }}} */

ext/gmp/tests/gh9308.phpt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Bug GH-9308: GMP throws the wrong error when a GMP object is passed to gmp_init()
3+
--EXTENSIONS--
4+
gmp
5+
--FILE--
6+
<?php
7+
declare(strict_types=1);
8+
9+
/* We need strict_types as GMP has a __toString() handler */
10+
11+
try {
12+
$gmp = gmp_init(gmp_init(123));
13+
} catch (\TypeError $e) {
14+
echo $e->getMessage(), \PHP_EOL;
15+
}
16+
17+
?>
18+
--EXPECT--
19+
gmp_init(): Argument #1 ($num) must be of type string|int, GMP given

0 commit comments

Comments
 (0)