]> granicus.if.org Git - php/commitdiff
Fixed bug #80545
authorJens de Nies <j.de.nies@protonmail.com>
Sun, 27 Dec 2020 20:15:06 +0000 (21:15 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 12 Jan 2021 08:50:27 +0000 (09:50 +0100)
This converts the remaining "non well-formed" warnings in bcmath
to ValueErrors, in line with the other warning promotions that
have been performed in this extension.

Closes GH-80545.

NEWS
ext/bcmath/bcmath.c
ext/bcmath/tests/bug80545.phpt [new file with mode: 0644]
ext/bcmath/tests/str2num_formatting.phpt

diff --git a/NEWS b/NEWS
index 1b9fd953a4625a4d1fef50e2741f47f915ced86e..d27f9b34c8fdeca70eb90a9232f595cbcfb4a70b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,10 @@ PHP                                                                        NEWS
   . Fixed bug #80384 (filter buffers entire read until file closed). (Adam
     Seitz, cmb)
 
+- BCMath:
+  . Fixed bug #80545 (bcadd('a', 'a') doesn't throw an exception).
+    (Jens de Nies)
+
 - Date:
   . Fixed bug #80376 (last day of the month causes runway cpu usage). (Derick)
 
index 95b820e4c4dfd0b7edcdace3ab1864025e2be414..870749af502dbfd7185b60881c224fe82135e2cd 100644 (file)
@@ -129,20 +129,23 @@ PHP_MINFO_FUNCTION(bcmath)
 
 /* {{{ php_str2num
    Convert to bc_num detecting scale */
-static void php_str2num(bc_num *num, char *str)
+static zend_result php_str2num(bc_num *num, char *str)
 {
        char *p;
 
        if (!(p = strchr(str, '.'))) {
                if (!bc_str2num(num, str, 0)) {
-                       php_error_docref(NULL, E_WARNING, "bcmath function argument is not well-formed");
+                       return FAILURE;
                }
-               return;
+
+               return SUCCESS;
        }
 
        if (!bc_str2num(num, str, strlen(p+1))) {
-               php_error_docref(NULL, E_WARNING, "bcmath function argument is not well-formed");
+               return FAILURE;
        }
+
+       return SUCCESS;
 }
 /* }}} */
 
@@ -174,15 +177,26 @@ PHP_FUNCTION(bcadd)
        bc_init_num(&first);
        bc_init_num(&second);
        bc_init_num(&result);
-       php_str2num(&first, ZSTR_VAL(left));
-       php_str2num(&second, ZSTR_VAL(right));
+
+       if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
+               zend_argument_value_error(1, "is not well-formed");
+               goto cleanup;
+       }
+
+       if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
+               zend_argument_value_error(2, "is not well-formed");
+               goto cleanup;
+       }
+
        bc_add (first, second, &result, scale);
 
        RETVAL_STR(bc_num2str_ex(result, scale));
-       bc_free_num(&first);
-       bc_free_num(&second);
-       bc_free_num(&result);
-       return;
+
+       cleanup: {
+               bc_free_num(&first);
+               bc_free_num(&second);
+               bc_free_num(&result);
+       };
 }
 /* }}} */
 
@@ -214,15 +228,26 @@ PHP_FUNCTION(bcsub)
        bc_init_num(&first);
        bc_init_num(&second);
        bc_init_num(&result);
-       php_str2num(&first, ZSTR_VAL(left));
-       php_str2num(&second, ZSTR_VAL(right));
+
+       if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
+               zend_argument_value_error(1, "is not well-formed");
+               goto cleanup;
+       }
+
+       if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
+               zend_argument_value_error(2, "is not well-formed");
+               goto cleanup;
+       }
+
        bc_sub (first, second, &result, scale);
 
        RETVAL_STR(bc_num2str_ex(result, scale));
-       bc_free_num(&first);
-       bc_free_num(&second);
-       bc_free_num(&result);
-       return;
+
+       cleanup: {
+               bc_free_num(&first);
+               bc_free_num(&second);
+               bc_free_num(&result);
+       };
 }
 /* }}} */
 
@@ -254,15 +279,26 @@ PHP_FUNCTION(bcmul)
        bc_init_num(&first);
        bc_init_num(&second);
        bc_init_num(&result);
-       php_str2num(&first, ZSTR_VAL(left));
-       php_str2num(&second, ZSTR_VAL(right));
+
+       if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
+               zend_argument_value_error(1, "is not well-formed");
+               goto cleanup;
+       }
+
+       if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
+               zend_argument_value_error(2, "is not well-formed");
+               goto cleanup;
+       }
+
        bc_multiply (first, second, &result, scale);
 
        RETVAL_STR(bc_num2str_ex(result, scale));
-       bc_free_num(&first);
-       bc_free_num(&second);
-       bc_free_num(&result);
-       return;
+
+       cleanup: {
+               bc_free_num(&first);
+               bc_free_num(&second);
+               bc_free_num(&result);
+       };
 }
 /* }}} */
 
@@ -294,8 +330,16 @@ PHP_FUNCTION(bcdiv)
        bc_init_num(&first);
        bc_init_num(&second);
        bc_init_num(&result);
-       php_str2num(&first, ZSTR_VAL(left));
-       php_str2num(&second, ZSTR_VAL(right));
+
+       if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
+               zend_argument_value_error(1, "is not well-formed");
+               goto cleanup;
+       }
+
+       if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
+               zend_argument_value_error(2, "is not well-formed");
+               goto cleanup;
+       }
 
        switch (bc_divide(first, second, &result, scale)) {
                case 0: /* OK */
@@ -306,10 +350,11 @@ PHP_FUNCTION(bcdiv)
                        break;
        }
 
-       bc_free_num(&first);
-       bc_free_num(&second);
-       bc_free_num(&result);
-       return;
+       cleanup: {
+               bc_free_num(&first);
+               bc_free_num(&second);
+               bc_free_num(&result);
+       };
 }
 /* }}} */
 
@@ -341,8 +386,16 @@ PHP_FUNCTION(bcmod)
        bc_init_num(&first);
        bc_init_num(&second);
        bc_init_num(&result);
-       php_str2num(&first, ZSTR_VAL(left));
-       php_str2num(&second, ZSTR_VAL(right));
+
+       if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
+               zend_argument_value_error(1, "is not well-formed");
+               goto cleanup;
+       }
+
+       if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
+               zend_argument_value_error(2, "is not well-formed");
+               goto cleanup;
+       }
 
        switch (bc_modulo(first, second, &result, scale)) {
                case 0:
@@ -353,9 +406,11 @@ PHP_FUNCTION(bcmod)
                        break;
        }
 
-       bc_free_num(&first);
-       bc_free_num(&second);
-       bc_free_num(&result);
+       cleanup: {
+               bc_free_num(&first);
+               bc_free_num(&second);
+               bc_free_num(&result);
+       };
 }
 /* }}} */
 
@@ -389,18 +444,32 @@ PHP_FUNCTION(bcpowmod)
        bc_init_num(&second);
        bc_init_num(&mod);
        bc_init_num(&result);
-       php_str2num(&first, ZSTR_VAL(left));
-       php_str2num(&second, ZSTR_VAL(right));
-       php_str2num(&mod, ZSTR_VAL(modulus));
+
+       if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
+               zend_argument_value_error(1, "is not well-formed");
+               goto cleanup;
+       }
+
+       if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
+               zend_argument_value_error(2, "is not well-formed");
+               goto cleanup;
+       }
+
+       if (php_str2num(&mod, ZSTR_VAL(modulus)) == FAILURE) {
+               zend_argument_value_error(3, "is not well-formed");
+               goto cleanup;
+       }
 
        if (bc_raisemod(first, second, mod, &result, scale) == SUCCESS) {
                RETVAL_STR(bc_num2str_ex(result, scale));
        }
 
-       bc_free_num(&first);
-       bc_free_num(&second);
-       bc_free_num(&mod);
-       bc_free_num(&result);
+       cleanup: {
+               bc_free_num(&first);
+               bc_free_num(&second);
+               bc_free_num(&mod);
+               bc_free_num(&result);
+       };
 }
 /* }}} */
 
@@ -432,14 +501,26 @@ PHP_FUNCTION(bcpow)
        bc_init_num(&first);
        bc_init_num(&second);
        bc_init_num(&result);
-       php_str2num(&first, ZSTR_VAL(left));
-       php_str2num(&second, ZSTR_VAL(right));
+
+       if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
+               zend_argument_value_error(1, "is not well-formed");
+               goto cleanup;
+       }
+
+       if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
+               zend_argument_value_error(2, "is not well-formed");
+               goto cleanup;
+       }
+
        bc_raise (first, second, &result, scale);
 
        RETVAL_STR(bc_num2str_ex(result, scale));
-       bc_free_num(&first);
-       bc_free_num(&second);
-       bc_free_num(&result);
+
+       cleanup: {
+               bc_free_num(&first);
+               bc_free_num(&second);
+               bc_free_num(&result);
+       };
 }
 /* }}} */
 
@@ -468,7 +549,11 @@ PHP_FUNCTION(bcsqrt)
        }
 
        bc_init_num(&result);
-       php_str2num(&result, ZSTR_VAL(left));
+
+       if (php_str2num(&result, ZSTR_VAL(left)) == FAILURE) {
+               zend_argument_value_error(1, "is not well-formed");
+               goto cleanup;
+       }
 
        if (bc_sqrt (&result, scale) != 0) {
                RETVAL_STR(bc_num2str_ex(result, scale));
@@ -476,8 +561,9 @@ PHP_FUNCTION(bcsqrt)
                zend_argument_value_error(1, "must be greater than or equal to 0");
        }
 
-       bc_free_num(&result);
-       return;
+       cleanup: {
+               bc_free_num(&result);
+       };
 }
 /* }}} */
 
@@ -510,16 +596,21 @@ PHP_FUNCTION(bccomp)
        bc_init_num(&second);
 
        if (!bc_str2num(&first, ZSTR_VAL(left), scale)) {
-               php_error_docref(NULL, E_WARNING, "bcmath function argument is not well-formed");
+               zend_argument_value_error(1, "is not well-formed");
+               goto cleanup;
        }
+
        if (!bc_str2num(&second, ZSTR_VAL(right), scale)) {
-               php_error_docref(NULL, E_WARNING, "bcmath function argument is not well-formed");
+               zend_argument_value_error(2, "is not well-formed");
+               goto cleanup;
        }
+
        RETVAL_LONG(bc_compare(first, second));
 
-       bc_free_num(&first);
-       bc_free_num(&second);
-       return;
+       cleanup: {
+               bc_free_num(&first);
+               bc_free_num(&second);
+       };
 }
 /* }}} */
 
diff --git a/ext/bcmath/tests/bug80545.phpt b/ext/bcmath/tests/bug80545.phpt
new file mode 100644 (file)
index 0000000..680c4c0
--- /dev/null
@@ -0,0 +1,25 @@
+--TEST--
+Bug #80545 (bcadd('a', 'a') and bcadd('1', 'a') doesn't throw an exception)
+--SKIPIF--
+<?php
+if (!extension_loaded('bcmath')) die('skip bcmath extension not available');
+?>
+--FILE--
+<?php
+
+try {
+    bcadd('a', 'a');
+} catch (\ValueError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+    bcadd('1', 'a');
+} catch (\ValueError $e) {
+    echo $e->getMessage();
+}
+
+?>
+--EXPECT--
+bcadd(): Argument #1 ($num1) is not well-formed
+bcadd(): Argument #2 ($num2) is not well-formed
\ No newline at end of file
index 090dd44d53d66809421a472293510f9159156a03..83e633bdaf1b4db287a8a9179523b2ba8939338f 100644 (file)
@@ -14,12 +14,39 @@ echo bcadd("", "2", 2),"\n";
 echo bcadd("+0", "2"), "\n";
 echo bcadd("-0", "2"), "\n";
 
-echo bcadd(" 0", "2");
-echo bcadd("1e1", "2");
-echo bcadd("1,1", "2");
-echo bcadd("Hello", "2");
-echo bcadd("1 1", "2");
-echo "\n", "\n";
+echo "\n";
+
+try {
+    echo bcadd(" 0", "2");
+} catch (\ValueError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+    echo bcadd("1e1", "2");
+} catch (\ValueError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+    echo bcadd("1,1", "2");
+} catch (\ValueError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+    echo bcadd("Hello", "2");
+} catch (\ValueError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+    echo bcadd("1 1", "2");
+} catch (\ValueError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
+echo "\n";
 
 echo bccomp("1", "2"),"\n";
 echo bccomp("1.1", "2", 2),"\n";
@@ -27,11 +54,38 @@ echo bccomp("", "2"),"\n";
 echo bccomp("+0", "2"), "\n";
 echo bccomp("-0", "2"), "\n";
 
-echo bccomp(" 0", "2");
-echo bccomp("1e1", "2");
-echo bccomp("1,1", "2");
-echo bccomp("Hello", "2");
-echo bccomp("1 1", "2");
+echo "\n";
+
+try {
+    echo bccomp(" 0", "2");
+} catch (\ValueError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+    echo bccomp("1e1", "2");
+} catch (\ValueError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+    echo bccomp("1,1", "2");
+} catch (\ValueError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+    echo bccomp("Hello", "2");
+} catch (\ValueError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+    echo bccomp("1 1", "2");
+} catch (\ValueError $e) {
+    echo $e->getMessage() . PHP_EOL;
+}
+
 ?>
 --EXPECTF--
 3
@@ -40,16 +94,11 @@ echo bccomp("1 1", "2");
 2
 2
 
-Warning: bcadd(): bcmath function argument is not well-formed in %s on line %d
-2
-Warning: bcadd(): bcmath function argument is not well-formed in %s on line %d
-2
-Warning: bcadd(): bcmath function argument is not well-formed in %s on line %d
-2
-Warning: bcadd(): bcmath function argument is not well-formed in %s on line %d
-2
-Warning: bcadd(): bcmath function argument is not well-formed in %s on line %d
-2
+bcadd(): Argument #1 ($num1) is not well-formed
+bcadd(): Argument #1 ($num1) is not well-formed
+bcadd(): Argument #1 ($num1) is not well-formed
+bcadd(): Argument #1 ($num1) is not well-formed
+bcadd(): Argument #1 ($num1) is not well-formed
 
 -1
 -1
@@ -57,13 +106,8 @@ Warning: bcadd(): bcmath function argument is not well-formed in %s on line %d
 -1
 -1
 
-Warning: bccomp(): bcmath function argument is not well-formed in %s on line %d
--1
-Warning: bccomp(): bcmath function argument is not well-formed in %s on line %d
--1
-Warning: bccomp(): bcmath function argument is not well-formed in %s on line %d
--1
-Warning: bccomp(): bcmath function argument is not well-formed in %s on line %d
--1
-Warning: bccomp(): bcmath function argument is not well-formed in %s on line %d
--1
\ No newline at end of file
+bccomp(): Argument #1 ($num1) is not well-formed
+bccomp(): Argument #1 ($num1) is not well-formed
+bccomp(): Argument #1 ($num1) is not well-formed
+bccomp(): Argument #1 ($num1) is not well-formed
+bccomp(): Argument #1 ($num1) is not well-formed
\ No newline at end of file