diff options
author | Vladyslav Startsev <17382248+vladyslavstartsev@users.noreply.github.com> | 2020-04-25 02:18:09 +0300 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2020-04-27 11:53:26 +0200 |
commit | b64aee97069fc77c141c787e5408d9e12f5971b4 (patch) | |
tree | 645099cfe50b3bbcff19d83374e4f7cc94d833f5 /ext/bcmath/bcmath.c | |
parent | 48a34bc1202e9664121c9e9aa004c79ac71af3f5 (diff) | |
download | php-git-b64aee97069fc77c141c787e5408d9e12f5971b4.tar.gz |
Ensure bcmath scale is between 0 and INT_MAX
Make sure bcmatch scale is between 0 and INT_MAX, both for the
ini setting, and all the functions accepting a scale argument.
A ValueError is thrown if a function argument is out of range.
Closes GH-5455.
Diffstat (limited to 'ext/bcmath/bcmath.c')
-rw-r--r-- | ext/bcmath/bcmath.c | 112 |
1 files changed, 85 insertions, 27 deletions
diff --git a/ext/bcmath/bcmath.c b/ext/bcmath/bcmath.c index 8c46ee0f93..61ee95b211 100644 --- a/ext/bcmath/bcmath.c +++ b/ext/bcmath/bcmath.c @@ -45,7 +45,7 @@ zend_module_entry bcmath_module_entry = { PHP_BCMATH_VERSION, PHP_MODULE_GLOBALS(bcmath), PHP_GINIT(bcmath), - PHP_GSHUTDOWN(bcmath), + PHP_GSHUTDOWN(bcmath), NULL, STANDARD_MODULE_PROPERTIES_EX }; @@ -57,9 +57,25 @@ ZEND_TSRMLS_CACHE_DEFINE() ZEND_GET_MODULE(bcmath) #endif +ZEND_INI_MH(OnUpdateScale) +{ + int *p; + zend_long tmp; + + tmp = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); + if (tmp < 0 || tmp > INT_MAX) { + return FAILURE; + } + + p = (int *) ZEND_INI_GET_ADDR(); + *p = (int) tmp; + + return SUCCESS; +} + /* {{{ PHP_INI */ PHP_INI_BEGIN() - STD_PHP_INI_ENTRY("bcmath.scale", "0", PHP_INI_ALL, OnUpdateLongGEZero, bc_precision, zend_bcmath_globals, bcmath_globals) + STD_PHP_INI_ENTRY("bcmath.scale", "0", PHP_INI_ALL, OnUpdateScale, bc_precision, zend_bcmath_globals, bcmath_globals) PHP_INI_END() /* }}} */ @@ -142,7 +158,7 @@ PHP_FUNCTION(bcadd) zend_string *left, *right; zend_long scale_param = 0; bc_num first, second, result; - int scale = (int)BCG(bc_precision); + int scale = BCG(bc_precision); ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(left) @@ -152,7 +168,11 @@ PHP_FUNCTION(bcadd) ZEND_PARSE_PARAMETERS_END(); if (ZEND_NUM_ARGS() == 3) { - scale = (int) (scale_param < 0 ? 0 : scale_param); + if (scale_param < 0 || scale_param > INT_MAX) { + zend_argument_value_error(3, "must be between 0 and %d", INT_MAX); + RETURN_THROWS(); + } + scale = (int) scale_param; } bc_init_num(&first); @@ -177,7 +197,7 @@ PHP_FUNCTION(bcsub) zend_string *left, *right; zend_long scale_param = 0; bc_num first, second, result; - int scale = (int)BCG(bc_precision); + int scale = BCG(bc_precision); ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(left) @@ -187,7 +207,11 @@ PHP_FUNCTION(bcsub) ZEND_PARSE_PARAMETERS_END(); if (ZEND_NUM_ARGS() == 3) { - scale = (int) ((int)scale_param < 0 ? 0 : scale_param); + if (scale_param < 0 || scale_param > INT_MAX) { + zend_argument_value_error(3, "must be between 0 and %d", INT_MAX); + RETURN_THROWS(); + } + scale = (int) scale_param; } bc_init_num(&first); @@ -212,7 +236,7 @@ PHP_FUNCTION(bcmul) zend_string *left, *right; zend_long scale_param = 0; bc_num first, second, result; - int scale = (int)BCG(bc_precision); + int scale = BCG(bc_precision); ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(left) @@ -222,7 +246,11 @@ PHP_FUNCTION(bcmul) ZEND_PARSE_PARAMETERS_END(); if (ZEND_NUM_ARGS() == 3) { - scale = (int) ((int)scale_param < 0 ? 0 : scale_param); + if (scale_param < 0 || scale_param > INT_MAX) { + zend_argument_value_error(3, "must be between 0 and %d", INT_MAX); + RETURN_THROWS(); + } + scale = (int) scale_param; } bc_init_num(&first); @@ -247,7 +275,7 @@ PHP_FUNCTION(bcdiv) zend_string *left, *right; zend_long scale_param = 0; bc_num first, second, result; - int scale = (int)BCG(bc_precision); + int scale = BCG(bc_precision); ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(left) @@ -257,7 +285,11 @@ PHP_FUNCTION(bcdiv) ZEND_PARSE_PARAMETERS_END(); if (ZEND_NUM_ARGS() == 3) { - scale = (int) ((int)scale_param < 0 ? 0 : scale_param); + if (scale_param < 0 || scale_param > INT_MAX) { + zend_argument_value_error(3, "must be between 0 and %d", INT_MAX); + RETURN_THROWS(); + } + scale = (int) scale_param; } bc_init_num(&first); @@ -289,7 +321,7 @@ PHP_FUNCTION(bcmod) zend_string *left, *right; zend_long scale_param = 0; bc_num first, second, result; - int scale = (int)BCG(bc_precision); + int scale = BCG(bc_precision); ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(left) @@ -299,7 +331,11 @@ PHP_FUNCTION(bcmod) ZEND_PARSE_PARAMETERS_END(); if (ZEND_NUM_ARGS() == 3) { - scale = (int) ((int)scale_param < 0 ? 0 : scale_param); + if (scale_param < 0 || scale_param > INT_MAX) { + zend_argument_value_error(3, "must be between 0 and %d", INT_MAX); + RETURN_THROWS(); + } + scale = (int) scale_param; } bc_init_num(&first); @@ -329,18 +365,26 @@ PHP_FUNCTION(bcmod) PHP_FUNCTION(bcpowmod) { zend_string *left, *right, *modulus; + zend_long scale_param = 0; bc_num first, second, mod, result; - zend_long scale = BCG(bc_precision); - int scale_int; + int scale = BCG(bc_precision); ZEND_PARSE_PARAMETERS_START(3, 4) Z_PARAM_STR(left) Z_PARAM_STR(right) Z_PARAM_STR(modulus) Z_PARAM_OPTIONAL - Z_PARAM_LONG(scale) + Z_PARAM_LONG(scale_param) ZEND_PARSE_PARAMETERS_END(); + if (ZEND_NUM_ARGS() == 4) { + if (scale_param < 0 || scale_param > INT_MAX) { + zend_argument_value_error(4, "must be between 0 and %d", INT_MAX); + RETURN_THROWS(); + } + scale = (int) scale_param; + } + bc_init_num(&first); bc_init_num(&second); bc_init_num(&mod); @@ -349,10 +393,8 @@ PHP_FUNCTION(bcpowmod) php_str2num(&second, ZSTR_VAL(right)); php_str2num(&mod, ZSTR_VAL(modulus)); - scale_int = (int) ((int)scale < 0 ? 0 : scale); - - if (bc_raisemod(first, second, mod, &result, scale_int) != -1) { - RETVAL_STR(bc_num2str_ex(result, scale_int)); + if (bc_raisemod(first, second, mod, &result, scale) != -1) { + RETVAL_STR(bc_num2str_ex(result, scale)); } else { RETVAL_FALSE; } @@ -372,7 +414,7 @@ PHP_FUNCTION(bcpow) zend_string *left, *right; zend_long scale_param = 0; bc_num first, second, result; - int scale = (int)BCG(bc_precision); + int scale = BCG(bc_precision); ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(left) @@ -382,7 +424,11 @@ PHP_FUNCTION(bcpow) ZEND_PARSE_PARAMETERS_END(); if (ZEND_NUM_ARGS() == 3) { - scale = (int) ((int)scale_param < 0 ? 0 : scale_param); + if (scale_param < 0 || scale_param > INT_MAX) { + zend_argument_value_error(3, "must be between 0 and %d", INT_MAX); + RETURN_THROWS(); + } + scale = (int) scale_param; } bc_init_num(&first); @@ -407,7 +453,7 @@ PHP_FUNCTION(bcsqrt) zend_string *left; zend_long scale_param = 0; bc_num result; - int scale = (int)BCG(bc_precision); + int scale = BCG(bc_precision); ZEND_PARSE_PARAMETERS_START(1, 2) Z_PARAM_STR(left) @@ -416,7 +462,11 @@ PHP_FUNCTION(bcsqrt) ZEND_PARSE_PARAMETERS_END(); if (ZEND_NUM_ARGS() == 2) { - scale = (int) ((int)scale_param < 0 ? 0 : scale_param); + if (scale_param < 0 || scale_param > INT_MAX) { + zend_argument_value_error(2, "must be between 0 and %d", INT_MAX); + RETURN_THROWS(); + } + scale = (int) scale_param; } bc_init_num(&result); @@ -440,7 +490,7 @@ PHP_FUNCTION(bccomp) zend_string *left, *right; zend_long scale_param = 0; bc_num first, second; - int scale = (int)BCG(bc_precision); + int scale = BCG(bc_precision); ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(left) @@ -450,7 +500,11 @@ PHP_FUNCTION(bccomp) ZEND_PARSE_PARAMETERS_END(); if (ZEND_NUM_ARGS() == 3) { - scale = (int) ((int)scale_param < 0 ? 0 : scale_param); + if (scale_param < 0 || scale_param > INT_MAX) { + zend_argument_value_error(3, "must be between 0 and %d", INT_MAX); + RETURN_THROWS(); + } + scale = (int) scale_param; } bc_init_num(&first); @@ -460,7 +514,7 @@ PHP_FUNCTION(bccomp) php_error_docref(NULL, E_WARNING, "bcmath function argument is not well-formed"); } if (!bc_str2num(&second, ZSTR_VAL(right), scale)) { - php_error_docref(NULL, E_WARNING, "bcmath function argument is not well-formed"); + php_error_docref(NULL, E_WARNING, "bcmath function argument is not well-formed"); } RETVAL_LONG(bc_compare(first, second)); @@ -484,7 +538,11 @@ PHP_FUNCTION(bcscale) old_scale = BCG(bc_precision); if (ZEND_NUM_ARGS() == 1) { - BCG(bc_precision) = ((int)new_scale < 0) ? 0 : new_scale; + if (new_scale < 0 || new_scale > INT_MAX) { + zend_argument_value_error(1, "must be between 0 and %d", INT_MAX); + RETURN_THROWS(); + } + BCG(bc_precision) = (int) new_scale; } RETURN_LONG(old_scale); |