Fix #80560: Strings containing only a base prefix return 0 object

Closes GH-6549.
This commit is contained in:
George Peter Banyard 2020-12-29 02:31:15 +01:00 committed by Christoph M. Becker
parent da0ca53f39
commit abecaab09f
2 changed files with 225 additions and 3 deletions

View File

@ -174,7 +174,7 @@ if (IS_GMP(zval)) { \
gmp_create(return_value, &gmpnumber) gmp_create(return_value, &gmpnumber)
static void gmp_strval(zval *result, mpz_t gmpnum, int base); static void gmp_strval(zval *result, mpz_t gmpnum, int base);
static int convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, uint32_t arg_pos); 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);
/* /*
@ -585,7 +585,7 @@ ZEND_MODULE_INFO_D(gmp)
/* {{{ convert_to_gmp /* {{{ convert_to_gmp
* Convert zval to be gmp number */ * Convert zval to be gmp number */
static int convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, uint32_t arg_pos) static zend_result convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, uint32_t arg_pos)
{ {
switch (Z_TYPE_P(val)) { switch (Z_TYPE_P(val)) {
case IS_LONG: case IS_LONG:
@ -596,7 +596,7 @@ static int convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, uint32_t a
zend_bool skip_lead = 0; zend_bool skip_lead = 0;
int ret; int ret;
if (Z_STRLEN_P(val) > 2 && numstr[0] == '0') { if (Z_STRLEN_P(val) >= 2 && numstr[0] == '0') {
if ((base == 0 || base == 16) && (numstr[1] == 'x' || numstr[1] == 'X')) { if ((base == 0 || base == 16) && (numstr[1] == 'x' || numstr[1] == 'X')) {
base = 16; base = 16;
skip_lead = 1; skip_lead = 1;

222
ext/gmp/tests/bug80560.phpt Normal file
View File

@ -0,0 +1,222 @@
--TEST--
Bug #80560: Strings containing only a base prefix return 0 object
--SKIPIF--
<?php if (!extension_loaded("gmp")) print "skip"; ?>
--FILE--
<?php
$functions1 = [
'gmp_init',
'gmp_export',
'gmp_intval',
'gmp_strval',
'gmp_neg',
'gmp_abs',
'gmp_fact',
'gmp_sqrt',
'gmp_sqrtrem',
'gmp_root',
'gmp_rootrem',
'gmp_pow',
'gmp_perfect_square',
'gmp_perfect_power',
'gmp_prob_prime',
'gmp_sign',
'gmp_random_seed',
'gmp_popcount',
'gmp_com',
];
$functions1_need_int_2 = [
'gmp_testbit',
'gmp_scan0',
'gmp_scan1',
'gmp_binomial',
];
$functions2 = [
'gmp_add',
'gmp_sub',
'gmp_mul',
'gmp_div',
'gmp_div_q',
'gmp_div_r',
'gmp_div_qr',
'gmp_divexact',
'gmp_mod',
'gmp_gcd',
'gmp_gcdext',
'gmp_lcm',
'gmp_invert',
'gmp_jacobi',
'gmp_legendre',
'gmp_kronecker',
'gmp_cmp',
'gmp_random_range',
'gmp_and',
'gmp_or',
'gmp_xor',
'gmp_hamdist',
'gmp_nextprime',
];
$functions3 = [
'gmp_powm',
];
echo 'Explicit base with gmp_init:', \PHP_EOL;
echo 'Hexadecimal', \PHP_EOL;
try {
var_dump(gmp_init('0X', 16));
} catch (\TypeError $e) {
echo $e->getMessage(), \PHP_EOL;
}
try {
var_dump(gmp_init('0x', 16));
} catch (\TypeError $e) {
echo $e->getMessage(), \PHP_EOL;
}
echo 'Binary', \PHP_EOL;
try {
var_dump(gmp_init('0B', 2));
} catch (\TypeError $e) {
echo $e->getMessage(), \PHP_EOL;
}
try {
var_dump(gmp_init('0b', 2));
} catch (\TypeError $e) {
echo $e->getMessage(), \PHP_EOL;
}
echo 'Fuzzing gmp functions:', \PHP_EOL;
foreach ($functions1 as $function) {
try {
$function('0B');
echo $function, ' failed with 0B', \PHP_EOL;
} catch (\TypeError) { }
try {
$function('0b');
echo $function, ' failed with 0b', \PHP_EOL;
} catch (\TypeError) { }
try {
$function('0X');
echo $function, ' failed with 0X', \PHP_EOL;
} catch (\TypeError) { }
try {
$function('0x');
echo $function, ' failed with 0x', \PHP_EOL;
} catch (\TypeError) { }
}
foreach ($functions1_need_int_2 as $function) {
try {
$function('0B', 1);
echo $function, ' failed with 0B', \PHP_EOL;
} catch (\TypeError) { }
try {
$function('0b', 1);
echo $function, ' failed with 0b', \PHP_EOL;
} catch (\TypeError) { }
try {
$function('0X', 1);
echo $function, ' failed with 0X', \PHP_EOL;
} catch (\TypeError) { }
try {
$function('0x', 1);
echo $function, ' failed with 0x', \PHP_EOL;
} catch (\TypeError) { }
}
foreach ($functions2 as $function) {
try {
$function('0B', 1);
echo $function, ' arg 1 failed with 0B', \PHP_EOL;
} catch (\TypeError) { }
try {
$function('0b', 1);
echo $function, ' arg 1 failed with 0b', \PHP_EOL;
} catch (\TypeError) { }
try {
$function('0X', 1);
echo $function, ' arg 1 failed with 0X', \PHP_EOL;
} catch (\TypeError) { }
try {
$function('0x', 1);
echo $function, ' arg 1 failed with 0x', \PHP_EOL;
} catch (\TypeError) { }
try {
$function(1, '0B');
echo $function, ' arg 2 failed with 0B', \PHP_EOL;
} catch (\TypeError) { }
try {
$function(1, '0b');
echo $function, ' arg 2 failed with 0b', \PHP_EOL;
} catch (\TypeError) { }
try {
$function(1, '0X');
echo $function, ' arg 2 failed with 0X', \PHP_EOL;
} catch (\TypeError) { }
try {
$function(1, '0x');
echo $function, ' arg 2 failed with 0x', \PHP_EOL;
} catch (\TypeError) { }
}
foreach ($functions3 as $function) {
try {
$function('0B', 1, 1);
echo $function, ' arg 1 failed with 0B', \PHP_EOL;
} catch (\TypeError) { }
try {
$function('0b', 1, 1);
echo $function, ' arg 1 failed with 0b', \PHP_EOL;
} catch (\TypeError) { }
try {
$function('0X', 1, 1);
echo $function, ' arg 1 failed with 0X', \PHP_EOL;
} catch (\TypeError) { }
try {
$function('0x', 1, 1);
echo $function, ' arg 1 failed with 0x', \PHP_EOL;
} catch (\TypeError) { }
try {
$function(1, '0B', 1);
echo $function, ' arg 2 failed with 0B', \PHP_EOL;
} catch (\TypeError) { }
try {
$function(1, '0b', 1);
echo $function, ' arg 2 failed with 0b', \PHP_EOL;
} catch (\TypeError) { }
try {
$function(1, '0X', 1);
echo $function, ' arg 2 failed with 0X', \PHP_EOL;
} catch (\TypeError) { }
try {
$function(1, '0x', 1);
echo $function, ' arg 2 failed with 0x', \PHP_EOL;
} catch (\TypeError) { }
try {
$function(1, 1, '0B');
echo $function, ' arg 3 failed with 0B', \PHP_EOL;
} catch (\TypeError) { }
try {
$function(1, 1, '0b');
echo $function, ' arg 3 failed with 0b', \PHP_EOL;
} catch (\TypeError) { }
try {
$function(1, 1, '0X');
echo $function, ' arg 3 failed with 0X', \PHP_EOL;
} catch (\TypeError) { }
try {
$function(1, 1, '0x');
echo $function, ' arg 3 failed with 0x', \PHP_EOL;
} catch (\TypeError) { }
}
echo "Done\n";
?>
--EXPECT--
Explicit base with gmp_init:
Hexadecimal
gmp_init(): Argument #1 ($num) is not an integer string
gmp_init(): Argument #1 ($num) is not an integer string
Binary
gmp_init(): Argument #1 ($num) is not an integer string
gmp_init(): Argument #1 ($num) is not an integer string
Fuzzing gmp functions:
Done