Skip to content

Commit

Permalink
Fix GH-9308 GMP throws the wrong error when a GMP object is passed to…
Browse files Browse the repository at this point in the history
… gmp_init()

Closes GH-9490
  • Loading branch information
Girgias committed Sep 13, 2022
1 parent d0b3096 commit 293e691
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 33 deletions.
4 changes: 4 additions & 0 deletions NEWS
Expand Up @@ -20,6 +20,10 @@ PHP NEWS
. Fixed bug #77780 ("Headers already sent..." when previous connection was
aborted). (Jakub Zelenka)

- GMP
. Fixed bug GH-9308 (GMP throws the wrong error when a GMP object is passed
to gmp_init()). (Girgias)

- PDO_PGSQL:
. Fixed bug GH-9411 (PgSQL large object resource is incorrectly closed).
(Yurunsoft)
Expand Down
76 changes: 43 additions & 33 deletions ext/gmp/gmp.c
Expand Up @@ -586,6 +586,33 @@ ZEND_MODULE_INFO_D(gmp)
}
/* }}} */

static zend_result convert_zstr_to_gmp(mpz_t gmp_number, const zend_string *val, zend_long base, uint32_t arg_pos)
{
const char *num_str = ZSTR_VAL(val);
bool skip_lead = false;

if (ZSTR_LEN(val) >= 2 && num_str[0] == '0') {
if ((base == 0 || base == 16) && (num_str[1] == 'x' || num_str[1] == 'X')) {
base = 16;
skip_lead = true;
} else if ((base == 0 || base == 2) && (num_str[1] == 'b' || num_str[1] == 'B')) {
base = 2;
skip_lead = true;
}
}

int gmp_ret = mpz_set_str(gmp_number, (skip_lead ? &num_str[2] : num_str), (int) base);
if (-1 == gmp_ret) {
if (arg_pos == 0) {
zend_value_error("Number is not an integer string");
} else {
zend_argument_value_error(arg_pos, "is not an integer string");
}
return FAILURE;
}

return SUCCESS;
}

/* {{{ convert_to_gmp
* Convert zval to be gmp number */
Expand All @@ -596,31 +623,7 @@ static zend_result convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, ui
mpz_set_si(gmpnumber, Z_LVAL_P(val));
return SUCCESS;
case IS_STRING: {
char *numstr = Z_STRVAL_P(val);
zend_bool skip_lead = 0;
int ret;

if (Z_STRLEN_P(val) >= 2 && numstr[0] == '0') {
if ((base == 0 || base == 16) && (numstr[1] == 'x' || numstr[1] == 'X')) {
base = 16;
skip_lead = 1;
} else if ((base == 0 || base == 2) && (numstr[1] == 'b' || numstr[1] == 'B')) {
base = 2;
skip_lead = 1;
}
}

ret = mpz_set_str(gmpnumber, (skip_lead ? &numstr[2] : numstr), (int) base);
if (-1 == ret) {
if (arg_pos == 0) {
zend_value_error("Number is not an integer string");
} else {
zend_argument_value_error(arg_pos, "is not an integer string");
}
return FAILURE;
}

return SUCCESS;
return convert_zstr_to_gmp(gmpnumber, Z_STR_P(val), base, arg_pos);
}
default: {
zend_long lval;
Expand Down Expand Up @@ -868,22 +871,29 @@ static inline void _gmp_unary_opl(INTERNAL_FUNCTION_PARAMETERS, gmp_unary_opl_t
/* {{{ Initializes GMP number */
ZEND_FUNCTION(gmp_init)
{
zval *number_arg;
mpz_ptr gmpnumber;
mpz_ptr gmp_number;
zend_string *arg_str = NULL;
zend_long arg_l = 0;
zend_long base = 0;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &number_arg, &base) == FAILURE) {
RETURN_THROWS();
}
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_STR_OR_LONG(arg_str, arg_l)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(base)
ZEND_PARSE_PARAMETERS_END();

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

INIT_GMP_RETVAL(gmpnumber);
if (convert_to_gmp(gmpnumber, number_arg, base, 1) == FAILURE) {
RETURN_THROWS();
INIT_GMP_RETVAL(gmp_number);
if (arg_str) {
if (convert_zstr_to_gmp(gmp_number, arg_str, base, 1) == FAILURE) {
RETURN_THROWS();
}
} else {
mpz_set_si(gmp_number, arg_l);
}
}
/* }}} */
Expand Down
19 changes: 19 additions & 0 deletions ext/gmp/tests/gh9308.phpt
@@ -0,0 +1,19 @@
--TEST--
Bug GH-9308: GMP throws the wrong error when a GMP object is passed to gmp_init()
--SKIPIF--
<?php extension_loaded('gmp') or die('skip gmp extension is not available'); ?>
--FILE--
<?php
declare(strict_types=1);

/* We need strict_types as GMP has a __toString() handler */

try {
$gmp = gmp_init(gmp_init(123));
} catch (\TypeError $e) {
echo $e->getMessage(), \PHP_EOL;
}

?>
--EXPECT--
gmp_init(): Argument #1 ($num) must be of type string|int, GMP given

0 comments on commit 293e691

Please sign in to comment.