Skip to content

Commit 3d5df06

Browse files
committed
Merge branch 'PHP-8.0' into PHP-8.1
2 parents 9af98cd + 293e691 commit 3d5df06

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
@@ -20,6 +20,10 @@ PHP NEWS
2020
. Fixed bug #77780 ("Headers already sent..." when previous connection was
2121
aborted). (Jakub Zelenka)
2222

23+
- GMP
24+
. Fixed bug GH-9308 (GMP throws the wrong error when a GMP object is passed
25+
to gmp_init()). (Girgias)
26+
2327
- PCRE:
2428
. Fixed pcre.jit on Apple Silicon. (Niklas Keller)
2529

ext/gmp/gmp.c

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,36 @@ ZEND_MODULE_INFO_D(gmp)
584584
}
585585
/* }}} */
586586

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

588618
/* {{{ convert_to_gmp
589619
* Convert zval to be gmp number */
@@ -594,34 +624,7 @@ static zend_result convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, ui
594624
mpz_set_si(gmpnumber, Z_LVAL_P(val));
595625
return SUCCESS;
596626
case IS_STRING: {
597-
char *numstr = Z_STRVAL_P(val);
598-
bool skip_lead = 0;
599-
int ret;
600-
601-
if (Z_STRLEN_P(val) >= 2 && numstr[0] == '0') {
602-
if ((base == 0 || base == 16) && (numstr[1] == 'x' || numstr[1] == 'X')) {
603-
base = 16;
604-
skip_lead = 1;
605-
} else if ((base == 0 || base == 8) && (numstr[1] == 'o' || numstr[1] == 'O')) {
606-
base = 8;
607-
skip_lead = 1;
608-
} else if ((base == 0 || base == 2) && (numstr[1] == 'b' || numstr[1] == 'B')) {
609-
base = 2;
610-
skip_lead = 1;
611-
}
612-
}
613-
614-
ret = mpz_set_str(gmpnumber, (skip_lead ? &numstr[2] : numstr), (int) base);
615-
if (-1 == ret) {
616-
if (arg_pos == 0) {
617-
zend_value_error("Number is not an integer string");
618-
} else {
619-
zend_argument_value_error(arg_pos, "is not an integer string");
620-
}
621-
return FAILURE;
622-
}
623-
624-
return SUCCESS;
627+
return convert_zstr_to_gmp(gmpnumber, Z_STR_P(val), base, arg_pos);
625628
}
626629
default: {
627630
zend_long lval;
@@ -869,22 +872,29 @@ static inline void _gmp_unary_opl(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_opl_t
869872
/* {{{ Initializes GMP number */
870873
ZEND_FUNCTION(gmp_init)
871874
{
872-
zval *number_arg;
873-
mpz_ptr gmpnumber;
875+
mpz_ptr gmp_number;
876+
zend_string *arg_str = NULL;
877+
zend_long arg_l = 0;
874878
zend_long base = 0;
875879

876-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &number_arg, &base) == FAILURE) {
877-
RETURN_THROWS();
878-
}
880+
ZEND_PARSE_PARAMETERS_START(1, 2)
881+
Z_PARAM_STR_OR_LONG(arg_str, arg_l)
882+
Z_PARAM_OPTIONAL
883+
Z_PARAM_LONG(base)
884+
ZEND_PARSE_PARAMETERS_END();
879885

880886
if (base && (base < 2 || base > GMP_MAX_BASE)) {
881887
zend_argument_value_error(2, "must be between 2 and %d", GMP_MAX_BASE);
882888
RETURN_THROWS();
883889
}
884890

885-
INIT_GMP_RETVAL(gmpnumber);
886-
if (convert_to_gmp(gmpnumber, number_arg, base, 1) == FAILURE) {
887-
RETURN_THROWS();
891+
INIT_GMP_RETVAL(gmp_number);
892+
if (arg_str) {
893+
if (convert_zstr_to_gmp(gmp_number, arg_str, base, 1) == FAILURE) {
894+
RETURN_THROWS();
895+
}
896+
} else {
897+
mpz_set_si(gmp_number, arg_l);
888898
}
889899
}
890900
/* }}} */

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)