]> granicus.if.org Git - php/commitdiff
Fix #80560: Strings containing only a base prefix return 0 object
authorGeorge Peter Banyard <girgias@php.net>
Tue, 29 Dec 2020 01:31:15 +0000 (02:31 +0100)
committerChristoph M. Becker <cmbecker69@gmx.de>
Wed, 30 Dec 2020 11:50:04 +0000 (12:50 +0100)
Closes GH-6549.

ext/gmp/gmp.c
ext/gmp/tests/bug80560.phpt [new file with mode: 0644]

index 33ed7fd93fb6431cc842772c94f3c13f0e632297..5bccdeca5c357a02157988d3091370bd99433d61 100644 (file)
@@ -174,7 +174,7 @@ if (IS_GMP(zval)) {                                               \
        gmp_create(return_value, &gmpnumber)
 
 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);
 
 /*
@@ -585,7 +585,7 @@ ZEND_MODULE_INFO_D(gmp)
 
 /* {{{ convert_to_gmp
  * 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)) {
        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;
                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')) {
                                base = 16;
                                skip_lead = 1;
diff --git a/ext/gmp/tests/bug80560.phpt b/ext/gmp/tests/bug80560.phpt
new file mode 100644 (file)
index 0000000..f1bf7dc
--- /dev/null
@@ -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