From 82dc9a31c335d8cf7aff68d76698bc3d24f761f8 Mon Sep 17 00:00:00 2001 From: kharhamel Date: Tue, 15 Oct 2019 17:51:39 +0200 Subject: [PATCH] Convert warnings to Errors in sprintf() functions Closes GH-4837. --- ext/standard/formatted_print.c | 71 +++++++++++-------- .../tests/file/fscanf_variation14.phpt | 8 ++- ext/standard/tests/strings/printf_64bit.phpt | 10 +-- ext/standard/tests/strings/printf_error.phpt | 60 +++++++++------- ext/standard/tests/strings/sprintf_error.phpt | 60 +++++++++------- .../tests/strings/vfprintf_error4.phpt | 11 +-- .../tests/strings/vfprintf_variation21.phpt | 21 +++--- .../tests/strings/vprintf_variation2.phpt | 35 ++++----- .../tests/strings/vsprintf_variation2.phpt | 26 +++---- tests/strings/002.phpt | 9 ++- 10 files changed, 171 insertions(+), 140 deletions(-) diff --git a/ext/standard/formatted_print.c b/ext/standard/formatted_print.c index b91a41de541..a5acaeea9bd 100644 --- a/ext/standard/formatted_print.c +++ b/ext/standard/formatted_print.c @@ -387,9 +387,12 @@ php_sprintf_getnumber(char **buffer, size_t *len) * "x" integer argument is printed as lowercase hexadecimal * "X" integer argument is printed as uppercase hexadecimal * + * nb_additional_parameters is used for throwing errors: + * - -1: ValueError is thrown (for vsprintf where args originates from an array) + * - 0 or more: ArgumentCountError is thrown */ static zend_string * -php_formatted_print(zval *z_format, zval *args, int argc) +php_formatted_print(zval *z_format, zval *args, int argc, int nb_additional_parameters) { size_t size = 240, outpos = 0; int alignment, currarg, adjusting, argnum, width, precision; @@ -397,6 +400,7 @@ php_formatted_print(zval *z_format, zval *args, int argc) zend_string *result; int always_sign; size_t format_len; + int bad_arg_number = 0; if (!try_convert_to_string(z_format)) { return NULL; @@ -407,6 +411,7 @@ php_formatted_print(zval *z_format, zval *args, int argc) result = zend_string_alloc(size, 0); currarg = 0; + argnum = 0; while (format_len) { int expprec; @@ -450,7 +455,7 @@ php_formatted_print(zval *z_format, zval *args, int argc) if (argnum <= 0) { zend_string_efree(result); - php_error_docref(NULL, E_WARNING, "Argument number must be greater than zero"); + zend_value_error("Argument number must be greater than zero"); return NULL; } argnum--; @@ -491,7 +496,7 @@ php_formatted_print(zval *z_format, zval *args, int argc) PRINTF_DEBUG(("sprintf: getting width\n")); if ((width = php_sprintf_getnumber(&format, &format_len)) < 0) { efree(result); - php_error_docref(NULL, E_WARNING, "Width must be greater than zero and less than %d", INT_MAX); + zend_value_error("Width must be greater than zero and less than %d", INT_MAX); return NULL; } adjusting |= ADJ_WIDTH; @@ -508,7 +513,7 @@ php_formatted_print(zval *z_format, zval *args, int argc) if (isdigit((int)*format)) { if ((precision = php_sprintf_getnumber(&format, &format_len)) < 0) { efree(result); - php_error_docref(NULL, E_WARNING, "Precision must be greater than zero and less than %d", INT_MAX); + zend_value_error("Precision must be greater than zero and less than %d", INT_MAX); return NULL; } adjusting |= ADJ_PRECISION; @@ -522,17 +527,17 @@ php_formatted_print(zval *z_format, zval *args, int argc) PRINTF_DEBUG(("sprintf: precision=%d\n", precision)); } - if (argnum >= argc) { - efree(result); - php_error_docref(NULL, E_WARNING, "Too few arguments"); - return NULL; - } - if (*format == 'l') { format++; format_len--; } PRINTF_DEBUG(("sprintf: format character='%c'\n", *format)); + + if (argnum >= argc) { + bad_arg_number = 1; + continue; + } + /* now we expect to find a type specifier */ tmp = &args[argnum]; switch (*format) { @@ -628,6 +633,16 @@ php_formatted_print(zval *z_format, zval *args, int argc) } } + if (bad_arg_number == 1) { + efree(result); + if (nb_additional_parameters == -1) { + zend_value_error("The arguments array must contain %d items, %d given", argnum + 1, argc); + } else { + zend_argument_count_error("%d parameters are required, %d given", argnum + nb_additional_parameters + 1, argc + nb_additional_parameters); + } + return NULL; + } + exit: /* possibly, we have to make sure we have room for the terminating null? */ ZSTR_VAL(result)[outpos]=0; @@ -660,7 +675,7 @@ php_formatted_print_get_array(zval *array, int *argc) } /* }}} */ -/* {{{ proto string|false sprintf(string format [, mixed arg1 [, mixed ...]]) +/* {{{ proto string sprintf(string format [, mixed arg1 [, mixed ...]]) Return a formatted string */ PHP_FUNCTION(user_sprintf) { @@ -673,15 +688,15 @@ PHP_FUNCTION(user_sprintf) Z_PARAM_VARIADIC('*', args, argc) ZEND_PARSE_PARAMETERS_END(); - result = php_formatted_print(format, args, argc); + result = php_formatted_print(format, args, argc, 1); if (result == NULL) { - RETURN_FALSE; + return; } RETVAL_STR(result); } /* }}} */ -/* {{{ proto string|false vsprintf(string format, array args) +/* {{{ proto string vsprintf(string format, array args) Return a formatted string */ PHP_FUNCTION(vsprintf) { @@ -696,16 +711,16 @@ PHP_FUNCTION(vsprintf) args = php_formatted_print_get_array(array, &argc); - result = php_formatted_print(format, args, argc); + result = php_formatted_print(format, args, argc, -1); efree(args); if (result == NULL) { - RETURN_FALSE; + return; } RETVAL_STR(result); } /* }}} */ -/* {{{ proto int|false printf(string format [, mixed arg1 [, mixed ...]]) +/* {{{ proto int printf(string format [, mixed arg1 [, mixed ...]]) Output a formatted string */ PHP_FUNCTION(user_printf) { @@ -719,9 +734,9 @@ PHP_FUNCTION(user_printf) Z_PARAM_VARIADIC('*', args, argc) ZEND_PARSE_PARAMETERS_END(); - result = php_formatted_print(format, args, argc); + result = php_formatted_print(format, args, argc, 1); if (result == NULL) { - RETURN_FALSE; + return; } rlen = PHPWRITE(ZSTR_VAL(result), ZSTR_LEN(result)); zend_string_efree(result); @@ -729,7 +744,7 @@ PHP_FUNCTION(user_printf) } /* }}} */ -/* {{{ proto int|false vprintf(string format, array args) +/* {{{ proto int vprintf(string format, array args) Output a formatted string */ PHP_FUNCTION(vprintf) { @@ -745,10 +760,10 @@ PHP_FUNCTION(vprintf) args = php_formatted_print_get_array(array, &argc); - result = php_formatted_print(format, args, argc); + result = php_formatted_print(format, args, argc, -1); efree(args); if (result == NULL) { - RETURN_FALSE; + return; } rlen = PHPWRITE(ZSTR_VAL(result), ZSTR_LEN(result)); zend_string_efree(result); @@ -756,7 +771,7 @@ PHP_FUNCTION(vprintf) } /* }}} */ -/* {{{ proto int|false fprintf(resource stream, string format [, mixed arg1 [, mixed ...]]) +/* {{{ proto int fprintf(resource stream, string format [, mixed arg1 [, mixed ...]]) Output a formatted string into a stream */ PHP_FUNCTION(fprintf) { @@ -777,9 +792,9 @@ PHP_FUNCTION(fprintf) php_stream_from_zval(stream, arg1); - result = php_formatted_print(format, args, argc); + result = php_formatted_print(format, args, argc, 2); if (result == NULL) { - RETURN_FALSE; + return; } php_stream_write(stream, ZSTR_VAL(result), ZSTR_LEN(result)); @@ -789,7 +804,7 @@ PHP_FUNCTION(fprintf) } /* }}} */ -/* {{{ proto int|false vfprintf(resource stream, string format, array args) +/* {{{ proto int vfprintf(resource stream, string format, array args) Output a formatted string into a stream */ PHP_FUNCTION(vfprintf) { @@ -812,10 +827,10 @@ PHP_FUNCTION(vfprintf) args = php_formatted_print_get_array(array, &argc); - result = php_formatted_print(format, args, argc); + result = php_formatted_print(format, args, argc, -1); efree(args); if (result == NULL) { - RETURN_FALSE; + return; } php_stream_write(stream, ZSTR_VAL(result), ZSTR_LEN(result)); diff --git a/ext/standard/tests/file/fscanf_variation14.phpt b/ext/standard/tests/file/fscanf_variation14.phpt index 47caaa3568a..151c975776b 100644 --- a/ext/standard/tests/file/fscanf_variation14.phpt +++ b/ext/standard/tests/file/fscanf_variation14.phpt @@ -76,8 +76,12 @@ $counter = 1; // writing to the file foreach($valid_strings as $string) { - @fprintf($file_handle, $string); - @fprintf($file_handle, "\n"); + try { + fprintf($file_handle, $string); + } catch (\ValueError $e) { + } catch (\ArgumentCountError $e) { + } + fprintf($file_handle, "\n"); } // closing the file fclose($file_handle); diff --git a/ext/standard/tests/strings/printf_64bit.phpt b/ext/standard/tests/strings/printf_64bit.phpt index 0106f71445b..9d3b4484958 100644 --- a/ext/standard/tests/strings/printf_64bit.phpt +++ b/ext/standard/tests/strings/printf_64bit.phpt @@ -39,7 +39,11 @@ echo "\n*** Output for insufficient number of arguments ***\n"; $string = "dingy%sflem%dwombat"; $nbr = 5; $name = "voudras"; -printf("%d $string %s", $nbr, $name); +try { + printf("%d $string %s", $nbr, $name); +} catch (\ArgumentCountError $e) { + print('Error found: '.$e->getMessage()); +} /* Scalar argument */ @@ -233,9 +237,7 @@ printf("%d", $tempstring); printf() expects at least 1 parameter, 0 given *** Output for insufficient number of arguments *** - -Warning: printf(): Too few arguments in %s on line %d - +Error found: 5 parameters are required, 3 given *** Output for scalar argument *** 3 *** Output for NULL as argument *** diff --git a/ext/standard/tests/strings/printf_error.phpt b/ext/standard/tests/strings/printf_error.phpt index aff95426e6a..e5bd8c7e21f 100644 --- a/ext/standard/tests/strings/printf_error.phpt +++ b/ext/standard/tests/strings/printf_error.phpt @@ -25,16 +25,40 @@ $arg1 = 'one'; $arg2 = 'two'; echo "\n-- Call printf with one argument less than expected --\n"; -var_dump( printf($format1) ); -var_dump( printf($format2,$arg1) ); -var_dump( printf($format3,$arg1,$arg2) ); +try { + var_dump( printf($format1) ); +} catch (\ArgumentCountError $e) { + echo $e->getMessage(), "\n"; +} +try { + var_dump( printf($format2,$arg1) ); +} catch (\ArgumentCountError $e) { + echo $e->getMessage(), "\n"; +} +try { + var_dump( printf($format3,$arg1,$arg2) ); +} catch (\ArgumentCountError $e) { + echo $e->getMessage(), "\n"; +} echo "\n-- Call printf with two argument less than expected --\n"; -var_dump( printf($format2) ); -var_dump( printf($format3,$arg1) ); +try { + var_dump( printf($format2) ); +} catch (\ArgumentCountError $e) { + echo $e->getMessage(), "\n"; +} +try { + var_dump( printf($format3,$arg1) ); +} catch (\ArgumentCountError $e) { + echo $e->getMessage(), "\n"; +} echo "\n-- Call printf with three argument less than expected --\n"; -var_dump( printf($format3) ); +try { + var_dump( printf($format3) ); +} catch (\ArgumentCountError $e) { + echo $e->getMessage(), "\n"; +} ?> ===DONE=== @@ -47,26 +71,14 @@ printf() expects at least 1 parameter, 0 given -- Testing printf() function with less than expected no. of arguments -- -- Call printf with one argument less than expected -- - -Warning: printf(): Too few arguments in %s on line %d -bool(false) - -Warning: printf(): Too few arguments in %s on line %d -bool(false) - -Warning: printf(): Too few arguments in %s on line %d -bool(false) +2 parameters are required, 1 given +3 parameters are required, 2 given +4 parameters are required, 3 given -- Call printf with two argument less than expected -- - -Warning: printf(): Too few arguments in %s on line %d -bool(false) - -Warning: printf(): Too few arguments in %s on line %d -bool(false) +3 parameters are required, 1 given +4 parameters are required, 2 given -- Call printf with three argument less than expected -- - -Warning: printf(): Too few arguments in %s on line %d -bool(false) +4 parameters are required, 1 given ===DONE=== diff --git a/ext/standard/tests/strings/sprintf_error.phpt b/ext/standard/tests/strings/sprintf_error.phpt index 1b21b8b141c..4ba7a539fea 100644 --- a/ext/standard/tests/strings/sprintf_error.phpt +++ b/ext/standard/tests/strings/sprintf_error.phpt @@ -25,16 +25,40 @@ $arg1 = 'one'; $arg2 = 'two'; // with one argument less than expected -var_dump( sprintf($format1) ); -var_dump( sprintf($format2,$arg1) ); -var_dump( sprintf($format3,$arg1,$arg2) ); +try { + var_dump( sprintf($format1) ); +} catch (\ArgumentCountError $e) { + echo $e->getMessage(), "\n"; +} +try { + var_dump( sprintf($format2,$arg1) ); +} catch (\ArgumentCountError $e) { + echo $e->getMessage(), "\n"; +} +try { + var_dump( sprintf($format3,$arg1,$arg2) ); +} catch (\ArgumentCountError $e) { + echo $e->getMessage(), "\n"; +} // with two argument less than expected -var_dump( sprintf($format2) ); -var_dump( sprintf($format3,$arg1) ); +try { + var_dump( sprintf($format2) ); +} catch (\ArgumentCountError $e) { + echo $e->getMessage(), "\n"; +} +try { + var_dump( sprintf($format3,$arg1) ); +} catch (\ArgumentCountError $e) { + echo $e->getMessage(), "\n"; +} // with three argument less than expected -var_dump( sprintf($format3) ); +try { + var_dump( sprintf($format3) ); +} catch (\ArgumentCountError $e) { + echo $e->getMessage(), "\n"; +} echo "Done"; ?> @@ -45,22 +69,10 @@ echo "Done"; sprintf() expects at least %d parameter, %d given -- Testing sprintf() function with less than expected no. of arguments -- - -Warning: sprintf(): Too few arguments in %s on line %d -bool(false) - -Warning: sprintf(): Too few arguments in %s on line %d -bool(false) - -Warning: sprintf(): Too few arguments in %s on line %d -bool(false) - -Warning: sprintf(): Too few arguments in %s on line %d -bool(false) - -Warning: sprintf(): Too few arguments in %s on line %d -bool(false) - -Warning: sprintf(): Too few arguments in %s on line %d -bool(false) +2 parameters are required, 1 given +3 parameters are required, 2 given +4 parameters are required, 3 given +3 parameters are required, 1 given +4 parameters are required, 2 given +4 parameters are required, 1 given Done diff --git a/ext/standard/tests/strings/vfprintf_error4.phpt b/ext/standard/tests/strings/vfprintf_error4.phpt index e54e34f4cdf..9ccd83b2d83 100644 --- a/ext/standard/tests/strings/vfprintf_error4.phpt +++ b/ext/standard/tests/strings/vfprintf_error4.phpt @@ -22,8 +22,11 @@ try { } catch (TypeError $e) { echo $e->getMessage(), "\n"; } -var_dump( vfprintf( $fp, 'Foo %$c-0202Sd', array( 2 ) ) ); - +try { + var_dump( vfprintf( $fp, 'Foo %$c-0202Sd', array( 2 ) ) ); +} catch(\ValueError $e) { + print('Error found: '.$e->getMessage().".\n"); +} // Close handle fclose( $fp ); @@ -39,7 +42,5 @@ unlink( $file ); --EXPECTF-- -- Testing vfprintf() function with other strangeties -- vfprintf() expects parameter 1 to be resource, string given - -Warning: vfprintf(): Argument number must be greater than zero in %s on line %d -bool(false) +Error found: Argument number must be greater than zero. ===DONE=== diff --git a/ext/standard/tests/strings/vfprintf_variation21.phpt b/ext/standard/tests/strings/vfprintf_variation21.phpt index 11f29e87acc..1358154f951 100644 --- a/ext/standard/tests/strings/vfprintf_variation21.phpt +++ b/ext/standard/tests/strings/vfprintf_variation21.phpt @@ -90,7 +90,11 @@ fprintf($fp, "\n*** Testing vprintf() with unexpected values for args argument * $counter = 1; foreach( $values as $value ) { fprintf($fp, "\n-- Iteration %d --\n",$counter); - vfprintf($fp, $format, $value); + try { + vfprintf($fp, $format, $value); + } catch (\ValueError $e) { + fwrite($fp, $e->getMessage() . "\n"); + } $counter++; } @@ -106,16 +110,6 @@ unlink($data_file); --EXPECTF-- *** Testing vfprintf() : with unexpected values for args argument *** -Warning: vfprintf(): Too few arguments in %s on line %d - -Warning: vfprintf(): Too few arguments in %s on line %d - -Warning: vfprintf(): Too few arguments in %s on line %d - -Warning: vfprintf(): Too few arguments in %s on line %d - -Warning: vfprintf(): Too few arguments in %s on line %d - *** Testing vprintf() with unexpected values for args argument *** -- Iteration 1 -- @@ -137,8 +131,10 @@ Warning: vfprintf(): Too few arguments in %s on line %d -- Iteration 9 -- 0.5 -- Iteration 10 -- +The arguments array must contain 1 items, 0 given -- Iteration 11 -- +The arguments array must contain 1 items, 0 given -- Iteration 12 -- 1 @@ -157,10 +153,13 @@ string -- Iteration 19 -- string -- Iteration 20 -- +The arguments array must contain 1 items, 0 given -- Iteration 21 -- +The arguments array must contain 1 items, 0 given -- Iteration 22 -- +The arguments array must contain 1 items, 0 given -- Iteration 23 -- Resource id #%d diff --git a/ext/standard/tests/strings/vprintf_variation2.phpt b/ext/standard/tests/strings/vprintf_variation2.phpt index 69e17d21a75..a26d3590bc8 100644 --- a/ext/standard/tests/strings/vprintf_variation2.phpt +++ b/ext/standard/tests/strings/vprintf_variation2.phpt @@ -84,9 +84,13 @@ $values = array( $counter = 1; foreach($values as $value) { echo "\n-- Iteration $counter --\n"; - $result = vprintf($format,$value); - echo "\n"; - var_dump($result); + try { + $result = vprintf($format,$value); + echo "\n"; + var_dump($result); + } catch (\ValueError $e) { + echo $e->getMessage(), "\n"; + } $counter++; }; @@ -135,16 +139,10 @@ int(13) int(3) -- Iteration 10 -- - -Warning: vprintf(): Too few arguments in %s on line %d - -bool(false) +The arguments array must contain 1 items, 0 given -- Iteration 11 -- - -Warning: vprintf(): Too few arguments in %s on line %d - -bool(false) +The arguments array must contain 1 items, 0 given -- Iteration 12 -- 1 @@ -179,22 +177,13 @@ string int(6) -- Iteration 20 -- - -Warning: vprintf(): Too few arguments in %s on line %d - -bool(false) +The arguments array must contain 1 items, 0 given -- Iteration 21 -- - -Warning: vprintf(): Too few arguments in %s on line %d - -bool(false) +The arguments array must contain 1 items, 0 given -- Iteration 22 -- - -Warning: vprintf(): Too few arguments in %s on line %d - -bool(false) +The arguments array must contain 1 items, 0 given -- Iteration 23 -- Resource id #%d diff --git a/ext/standard/tests/strings/vsprintf_variation2.phpt b/ext/standard/tests/strings/vsprintf_variation2.phpt index 838093cdb16..3af9b854fe1 100644 --- a/ext/standard/tests/strings/vsprintf_variation2.phpt +++ b/ext/standard/tests/strings/vsprintf_variation2.phpt @@ -84,7 +84,11 @@ $values = array( $counter = 1; foreach($values as $value) { echo "\n-- Iteration $counter --\n"; - var_dump( vsprintf($format,$value) ); + try { + var_dump( vsprintf($format,$value) ); + } catch (\ValueError $e) { + echo $e->getMessage(), "\n"; + } $counter++; }; @@ -124,14 +128,10 @@ string(13) "1.07654321E-9" string(3) "0.5" -- Iteration 10 -- - -Warning: vsprintf(): Too few arguments in %s on line %d -bool(false) +The arguments array must contain 1 items, 0 given -- Iteration 11 -- - -Warning: vsprintf(): Too few arguments in %s on line %d -bool(false) +The arguments array must contain 1 items, 0 given -- Iteration 12 -- string(1) "1" @@ -158,19 +158,13 @@ string(6) "string" string(6) "string" -- Iteration 20 -- - -Warning: vsprintf(): Too few arguments in %s on line %d -bool(false) +The arguments array must contain 1 items, 0 given -- Iteration 21 -- - -Warning: vsprintf(): Too few arguments in %s on line %d -bool(false) +The arguments array must contain 1 items, 0 given -- Iteration 22 -- - -Warning: vsprintf(): Too few arguments in %s on line %d -bool(false) +The arguments array must contain 1 items, 0 given -- Iteration 23 -- string(%d) "Resource id #%d" diff --git a/tests/strings/002.phpt b/tests/strings/002.phpt index 5e820910884..a43a68c88b9 100644 --- a/tests/strings/002.phpt +++ b/tests/strings/002.phpt @@ -2,7 +2,6 @@ Formatted print functions --FILE-- getMessage()."\n"); +} vprintf("vprintf test 1:%2\$-2d %1\$2d\n", array(1, 2)); @@ -79,5 +82,5 @@ printf test 26:2 1 printf test 27:3 1 2 printf test 28:02 1 printf test 29:2 1 -printf test 30:x +printf test 30:Error found: Argument number must be greater than zero vprintf test 1:2 1