Skip to content

Improve argument error messages of ext/standard #5198

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 33 additions & 8 deletions Zend/zend_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(int num, char *e
}
/* }}} */

ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error(zend_class_entry *error_ce, uint32_t arg_num, const char *format, ...) /* {{{ */
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic(zend_class_entry *error_ce, uint32_t arg_num, const char *format, va_list va) /* {{{ */
{
const char *space;
const char *class_name;
Expand All @@ -254,20 +254,45 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error(zend_class_entry *erro
class_name = get_active_class_name(&space);
arg_name = get_active_function_arg_name(arg_num);

va_list va;
va_start(va, format);
zend_vspprintf(&message, 0, format, va);
va_end(va);

zend_throw_error(error_ce, "%s%s%s(): Argument #%d%s%s%s %s",
class_name, space, get_active_function_name(),
arg_num, arg_name ? " ($" : "", arg_name ? arg_name : "", arg_name ? ")" : "",
message
class_name, space, get_active_function_name(), arg_num,
arg_name ? " ($" : "", arg_name ? arg_name : "", arg_name ? ")" : "", message
);
efree(message);
}
/* }}} */

ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error(zend_class_entry *error_ce, uint32_t arg_num, const char *format, ...) /* {{{ */
{
va_list va;

va_start(va, format);
zend_argument_error_variadic(error_ce, arg_num, format, va);
va_end(va);
}
/* }}} */

ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_type_error(uint32_t arg_num, const char *format, ...) /* {{{ */
{
va_list va;

va_start(va, format);
zend_argument_error_variadic(zend_ce_type_error, arg_num, format, va);
va_end(va);
}
/* }}} */

ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_value_error(uint32_t arg_num, const char *format, ...) /* {{{ */
{
va_list va;

va_start(va, format);
zend_argument_error_variadic(zend_ce_value_error, arg_num, format, va);
va_end(va);
}
/* }}} */

ZEND_API int ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **pce, int num, int check_null) /* {{{ */
{
zend_class_entry *ce_base = *pce;
Expand Down
6 changes: 2 additions & 4 deletions Zend/zend_API.h
Original file line number Diff line number Diff line change
Expand Up @@ -1154,10 +1154,8 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(int num, z
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(int num, const char *name, zval *arg);
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(int num, char *error);
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error(zend_class_entry *error_ce, uint32_t arg_num, const char *format, ...);
#define zend_argument_type_error(arg_num, ...) \
zend_argument_error(zend_ce_type_error, arg_num, __VA_ARGS__)
#define zend_argument_value_error(arg_num, ...) \
zend_argument_error(zend_ce_value_error, arg_num, __VA_ARGS__)
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_type_error(uint32_t arg_num, const char *format, ...);
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_value_error(uint32_t arg_num, const char *format, ...);

#define ZPP_ERROR_OK 0
#define ZPP_ERROR_FAILURE 1
Expand Down
44 changes: 22 additions & 22 deletions ext/standard/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -1191,13 +1191,13 @@ PHP_FUNCTION(min)
zval *result;

if (Z_TYPE(args[0]) != IS_ARRAY) {
zend_type_error("When only one parameter is given, it must be an array");
zend_argument_type_error(1, "must be of type array, %s given", zend_zval_type_name(&args[0]));
RETURN_THROWS();
} else {
if ((result = zend_hash_minmax(Z_ARRVAL(args[0]), php_array_data_compare, 0)) != NULL) {
ZVAL_COPY_DEREF(return_value, result);
} else {
zend_value_error("Array must contain at least one element");
zend_argument_value_error(1, "must contain at least one element");
RETURN_THROWS();
}
}
Expand Down Expand Up @@ -1238,13 +1238,13 @@ PHP_FUNCTION(max)
zval *result;

if (Z_TYPE(args[0]) != IS_ARRAY) {
zend_type_error("When only one parameter is given, it must be an array");
zend_argument_type_error(1, "must be of type array, %s given", zend_zval_type_name(&args[0]));
RETURN_THROWS();
} else {
if ((result = zend_hash_minmax(Z_ARRVAL(args[0]), php_array_data_compare, 1)) != NULL) {
ZVAL_COPY_DEREF(return_value, result);
} else {
zend_value_error("Array must contain at least one element");
zend_argument_value_error(1, "must contain at least one element");
RETURN_THROWS();
}
}
Expand Down Expand Up @@ -3718,7 +3718,7 @@ static zend_always_inline void php_array_replace_wrapper(INTERNAL_FUNCTION_PARAM
zval *arg = args + i;

if (Z_TYPE_P(arg) != IS_ARRAY) {
zend_type_error("Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(arg));
zend_argument_type_error(i + 1, "must be of type array, %s given", zend_zval_type_name(arg));
RETURN_THROWS();
}
}
Expand Down Expand Up @@ -3762,7 +3762,7 @@ static zend_always_inline void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMET
zval *arg = args + i;

if (Z_TYPE_P(arg) != IS_ARRAY) {
zend_type_error("Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(arg));
zend_argument_type_error(i + 1, "must be of type array, %s given", zend_zval_type_name(arg));
RETURN_THROWS();
}
count += zend_hash_num_elements(Z_ARRVAL_P(arg));
Expand Down Expand Up @@ -4654,7 +4654,7 @@ static void php_array_intersect_key(INTERNAL_FUNCTION_PARAMETERS, int data_compa

for (i = 0; i < argc; i++) {
if (Z_TYPE(args[i]) != IS_ARRAY) {
zend_type_error("Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));
zend_argument_type_error(i + 1, "must be of type array, %s given", zend_zval_type_name(&args[i]));
RETURN_THROWS();
}
}
Expand Down Expand Up @@ -4819,7 +4819,7 @@ static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int

for (i = 0; i < arr_argc; i++) {
if (Z_TYPE(args[i]) != IS_ARRAY) {
zend_type_error("Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));
zend_argument_type_error(i + 1, "must be of type array, %s given", zend_zval_type_name(&args[i]));
arr_argc = i; /* only free up to i - 1 */
goto out;
}
Expand Down Expand Up @@ -5061,7 +5061,7 @@ static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_ty

for (i = 0; i < argc; i++) {
if (Z_TYPE(args[i]) != IS_ARRAY) {
zend_type_error("Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));
zend_argument_type_error(i + 1, "must be of type array, %s given", zend_zval_type_name(&args[i]));
RETURN_THROWS();
}
}
Expand Down Expand Up @@ -5226,7 +5226,7 @@ static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_

for (i = 0; i < arr_argc; i++) {
if (Z_TYPE(args[i]) != IS_ARRAY) {
zend_type_error("Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));
zend_argument_type_error(i + 1, "must be of type array, %s given", zend_zval_type_name(&args[i]));
arr_argc = i; /* only free up to i - 1 */
goto out;
}
Expand Down Expand Up @@ -5405,15 +5405,15 @@ PHP_FUNCTION(array_diff)
ZEND_PARSE_PARAMETERS_END();

if (Z_TYPE(args[0]) != IS_ARRAY) {
zend_type_error("Expected parameter 1 to be an array, %s given", zend_zval_type_name(&args[0]));
zend_argument_type_error(1, "must be of type array, %s given", zend_zval_type_name(&args[0]));
RETURN_THROWS();
}

num = zend_hash_num_elements(Z_ARRVAL(args[0]));
if (num == 0) {
for (i = 1; i < argc; i++) {
if (Z_TYPE(args[i]) != IS_ARRAY) {
zend_type_error("Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));
zend_argument_type_error(i + 1, "must be of type array, %s given", zend_zval_type_name(&args[i]));
RETURN_THROWS();
}
}
Expand All @@ -5430,7 +5430,7 @@ PHP_FUNCTION(array_diff)
if (!value) {
for (i = 1; i < argc; i++) {
if (Z_TYPE(args[i]) != IS_ARRAY) {
zend_type_error("Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));
zend_argument_type_error(i + 1, "must be of type array, %s given", zend_zval_type_name(&args[i]));
RETURN_THROWS();
}
}
Expand All @@ -5441,7 +5441,7 @@ PHP_FUNCTION(array_diff)

for (i = 1; i < argc; i++) {
if (Z_TYPE(args[i]) != IS_ARRAY) {
zend_type_error("Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));
zend_argument_type_error(i + 1, "must be of type array, %s given", zend_zval_type_name(&args[i]));
RETURN_THROWS();
}
if (!found) {
Expand Down Expand Up @@ -5471,7 +5471,7 @@ PHP_FUNCTION(array_diff)
num = 0;
for (i = 1; i < argc; i++) {
if (Z_TYPE(args[i]) != IS_ARRAY) {
zend_type_error("Expected parameter %d to be an array, %s given", i + 1, zend_zval_type_name(&args[i]));
zend_argument_type_error(i + 1, "must be of type array, %s given", zend_zval_type_name(&args[i]));
RETURN_THROWS();
}
num += zend_hash_num_elements(Z_ARRVAL(args[i]));
Expand Down Expand Up @@ -5656,7 +5656,7 @@ PHP_FUNCTION(array_multisort)
sort_order = Z_LVAL_P(arg) == PHP_SORT_DESC ? PHP_SORT_DESC : PHP_SORT_ASC;
parse_state[MULTISORT_ORDER] = 0;
} else {
zend_type_error("Argument #%d is expected to be an array or sorting flag that has not already been specified", i + 1);
zend_argument_type_error(i + 1, "must be an array or a sort flag that has not already been specified");
MULTISORT_ABORT;
}
break;
Expand All @@ -5672,19 +5672,19 @@ PHP_FUNCTION(array_multisort)
sort_type = (int)Z_LVAL_P(arg);
parse_state[MULTISORT_TYPE] = 0;
} else {
zend_type_error("Argument #%d is expected to be an array or sorting flag that has not already been specified", i + 1);
zend_argument_type_error(i + 1, "must be an array or a sort flag that has not already been specified");
MULTISORT_ABORT;
}
break;

default:
zend_type_error("Argument #%d is an unknown sort flag", i + 1);
zend_argument_value_error(i + 1, "must be a valid sort flag");
MULTISORT_ABORT;
break;

}
} else {
zend_type_error("Argument #%d is expected to be an array or a sort flag", i + 1);
zend_argument_type_error(i + 1, "must be an array or a sort flag");
MULTISORT_ABORT;
}
}
Expand Down Expand Up @@ -6120,7 +6120,7 @@ PHP_FUNCTION(array_map)
int ret;

if (Z_TYPE(arrays[0]) != IS_ARRAY) {
zend_type_error("Expected parameter 2 to be an array, %s given", zend_zval_type_name(&arrays[0]));
zend_argument_type_error(2, "must be of type array, %s given", zend_zval_type_name(&arrays[0]));
RETURN_THROWS();
}
maxlen = zend_hash_num_elements(Z_ARRVAL(arrays[0]));
Expand Down Expand Up @@ -6161,7 +6161,7 @@ PHP_FUNCTION(array_map)

for (i = 0; i < n_arrays; i++) {
if (Z_TYPE(arrays[i]) != IS_ARRAY) {
zend_type_error("Expected parameter %d to be an array, %s given", i + 2, zend_zval_type_name(&arrays[i]));
zend_argument_type_error(i + 2, "must be of type array, %s given", zend_zval_type_name(&arrays[i]));
efree(array_pos);
RETURN_THROWS();
}
Expand Down Expand Up @@ -6291,7 +6291,7 @@ PHP_FUNCTION(array_key_exists)
RETVAL_BOOL(zend_hash_index_exists(ht, Z_RES_HANDLE_P(key)));
break;
default:
zend_type_error("Illegal offset type");
zend_argument_type_error(1, "must be a valid array offset type");
break;
}
}
Expand Down
8 changes: 4 additions & 4 deletions ext/standard/basic_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -1938,7 +1938,7 @@ PHP_FUNCTION(sleep)
ZEND_PARSE_PARAMETERS_END();

if (num < 0) {
zend_value_error("Number of seconds must be greater than or equal to 0");
zend_argument_value_error(1, "must be greater than or equal to 0");
RETURN_THROWS();
}

Expand All @@ -1958,7 +1958,7 @@ PHP_FUNCTION(usleep)
ZEND_PARSE_PARAMETERS_END();

if (num < 0) {
zend_value_error("Number of microseconds must be greater than or equal to 0");
zend_argument_value_error(1, "must be greater than or equal to 0");
RETURN_THROWS();
}
if (usleep((unsigned int)num) < 0) {
Expand All @@ -1985,11 +1985,11 @@ PHP_FUNCTION(time_nanosleep)
ZEND_PARSE_PARAMETERS_END();

if (tv_sec < 0) {
zend_value_error("The seconds value must be greater than 0");
zend_argument_value_error(1, "must be greater than or equal to 0");
RETURN_THROWS();
}
if (tv_nsec < 0) {
zend_value_error("The nanoseconds value must be greater than 0");
zend_argument_value_error(2, "must be greater than or equal to 0");
RETURN_THROWS();
}

Expand Down
4 changes: 2 additions & 2 deletions ext/standard/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ PHP_FUNCTION(escapeshellcmd)

if (command_len) {
if (command_len != strlen(command)) {
zend_type_error("Input string contains NULL bytes");
zend_argument_type_error(1, "must not contain any null bytes");
RETURN_THROWS();
}
RETVAL_STR(php_escape_shell_cmd(command));
Expand All @@ -506,7 +506,7 @@ PHP_FUNCTION(escapeshellarg)
ZEND_PARSE_PARAMETERS_END();

if (argument_len != strlen(argument)) {
zend_type_error("Input string contains NULL bytes");
zend_argument_type_error(1, "must not contain any null bytes");
RETURN_THROWS();
}

Expand Down
16 changes: 8 additions & 8 deletions ext/standard/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ PHP_FUNCTION(file_get_contents)
ZEND_PARSE_PARAMETERS_END();

if (ZEND_NUM_ARGS() == 5 && maxlen < 0) {
zend_value_error("Length must be greater than or equal to zero");
zend_argument_value_error(5, "must be greater than or equal to 0");
RETURN_THROWS();
}

Expand Down Expand Up @@ -1040,7 +1040,7 @@ PHPAPI PHP_FUNCTION(fgets)
efree(buf);
} else if (argc > 1) {
if (len <= 0) {
zend_value_error("Length parameter must be greater than 0");
zend_argument_value_error(2, "must be greater than 0");
RETURN_THROWS();
}

Expand Down Expand Up @@ -1750,7 +1750,7 @@ PHPAPI PHP_FUNCTION(fread)
PHP_STREAM_TO_ZVAL(stream, res);

if (len <= 0) {
zend_value_error("Length parameter must be greater than 0");
zend_argument_value_error(2, "must be greater than 0");
RETURN_THROWS();
}

Expand Down Expand Up @@ -1829,7 +1829,7 @@ PHP_FUNCTION(fputcsv)
if (delimiter_str != NULL) {
/* Make sure that there is at least one character in string */
if (delimiter_str_len < 1) {
zend_value_error("delimiter must be a character");
zend_argument_value_error(3, "must be a single character");
RETURN_THROWS();
} else if (delimiter_str_len > 1) {
php_error_docref(NULL, E_NOTICE, "delimiter must be a single character");
Expand All @@ -1841,7 +1841,7 @@ PHP_FUNCTION(fputcsv)

if (enclosure_str != NULL) {
if (enclosure_str_len < 1) {
zend_value_error("enclosure must be a character");
zend_argument_value_error(4, "must be a single character");
RETURN_THROWS();
} else if (enclosure_str_len > 1) {
php_error_docref(NULL, E_NOTICE, "enclosure must be a single character");
Expand Down Expand Up @@ -1967,7 +1967,7 @@ PHP_FUNCTION(fgetcsv)
if (delimiter_str != NULL) {
/* Make sure that there is at least one character in string */
if (delimiter_str_len < 1) {
zend_value_error("delimiter must be a character");
zend_argument_value_error(3, "must be a single character");
RETURN_THROWS();
} else if (delimiter_str_len > 1) {
php_error_docref(NULL, E_NOTICE, "delimiter must be a single character");
Expand All @@ -1979,7 +1979,7 @@ PHP_FUNCTION(fgetcsv)

if (enclosure_str != NULL) {
if (enclosure_str_len < 1) {
zend_value_error("enclosure must be a character");
zend_argument_value_error(4, "must be a single character");
RETURN_THROWS();
} else if (enclosure_str_len > 1) {
php_error_docref(NULL, E_NOTICE, "enclosure must be a single character");
Expand All @@ -2004,7 +2004,7 @@ PHP_FUNCTION(fgetcsv)
if (len_zv != NULL && Z_TYPE_P(len_zv) != IS_NULL) {
len = zval_get_long(len_zv);
if (len < 0) {
zend_value_error("Length parameter may not be negative");
zend_argument_value_error(2, "must be a greater than or equal to 0");
RETURN_THROWS();
} else if (len == 0) {
len = -1;
Expand Down
Loading