Convert warnings to Errors in sprintf() functions

Closes GH-4837.
This commit is contained in:
kharhamel 2019-10-15 17:51:39 +02:00 committed by Nikita Popov
parent 9d48bf5152
commit 82dc9a31c3
10 changed files with 171 additions and 140 deletions

View File

@ -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));

View File

@ -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);

View File

@ -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 ***

View File

@ -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===

View File

@ -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

View File

@ -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===

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -2,7 +2,6 @@
Formatted print functions
--FILE--
<?php
error_reporting(0);
$fp = fopen("php://stdout", "w") or die("Arrggsgg!!");
$x = fprintf($fp, "fprintf test 1:%.5s", "abcdefghij");
@ -40,7 +39,11 @@ printf("printf test 26:%2\$d %1\$d\n", 1, 2);
printf("printf test 27:%3\$d %d %d\n", 1, 2, 3);
printf("printf test 28:%2\$02d %1\$2d\n", 1, 2);
printf("printf test 29:%2\$-2d %1\$2d\n", 1, 2);
print("printf test 30:"); printf("%0\$s", 1); print("x\n");
try {
print("printf test 30:"); printf("%0\$s", 1); print("x\n");
} catch(\ValueError $e) {
print('Error found: '.$e->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