Skip to content

Commit 231e0e1

Browse files
committed
Protected hapless internal functions against extra named params
1 parent eab997c commit 231e0e1

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

Zend/tests/named_params/internal_variadics.phpt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,19 @@ Named params on internal functions: Variadic functions
33
--FILE--
44
<?php
55

6-
array_merge([1, 2], a: [3, 4]);
6+
try {
7+
array_merge([1, 2], a: [3, 4]);
8+
} catch (ArgumentCountError $e) {
9+
echo $e->getMessage(), "\n";
10+
}
11+
12+
try {
13+
array_diff_key([1, 2], [3, 4], a: [5, 6]);
14+
} catch (ArgumentCountError $e) {
15+
echo $e->getMessage(), "\n";
16+
}
717

818
?>
919
--EXPECT--
10-
20+
array_merge() does not accept unknown named parameters
21+
array_diff_key() does not accept unknown named parameters

Zend/zend_API.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,14 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(int num, char *e
283283
}
284284
/* }}} */
285285

286+
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_unexpected_extra_named_error(void)
287+
{
288+
const char *space;
289+
const char *class_name = get_active_class_name(&space);
290+
zend_argument_count_error("%s%s%s() does not accept unknown named parameters",
291+
class_name, space, get_active_function_name());
292+
}
293+
286294
static ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic(zend_class_entry *error_ce, uint32_t arg_num, const char *format, va_list va) /* {{{ */
287295
{
288296
const char *space;
@@ -927,6 +935,11 @@ static int zend_parse_va_args(uint32_t num_args, const char *type_spec, va_list
927935
}
928936
/* mark the beginning of varargs */
929937
post_varargs = max_num_args;
938+
939+
if (ZEND_CALL_INFO(EG(current_execute_data)) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
940+
zend_unexpected_extra_named_error();
941+
return FAILURE;
942+
}
930943
break;
931944

932945
default:

Zend/zend_API.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,6 +1240,8 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_null_error(i
12401240
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_string_or_class_error(int num, const char *name, zval *arg);
12411241
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_string_or_class_or_null_error(int num, const char *name, zval *arg);
12421242
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(int num, char *error);
1243+
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_unexpected_extra_named_error(void);
1244+
12431245
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_error(zend_class_entry *error_ce, uint32_t arg_num, const char *format, ...);
12441246
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_type_error(uint32_t arg_num, const char *format, ...);
12451247
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_value_error(uint32_t arg_num, const char *format, ...);
@@ -1253,6 +1255,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_value_error(uint32_t arg_num
12531255
#define ZPP_ERROR_WRONG_COUNT 6
12541256
#define ZPP_ERROR_WRONG_STRING_OR_CLASS 7
12551257
#define ZPP_ERROR_WRONG_STRING_OR_CLASS_OR_NULL 8
1258+
#define ZPP_ERROR_UNEXPECTED_EXTRA_NAMED 9
12561259

12571260
#define ZEND_PARSE_PARAMETERS_START_EX(flags, min_num_args, max_num_args) do { \
12581261
const int _flags = (flags); \
@@ -1311,6 +1314,8 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_value_error(uint32_t arg_num
13111314
zend_wrong_parameter_string_or_class_error(_i, _error, _arg); \
13121315
} else if (_error_code == ZPP_ERROR_WRONG_STRING_OR_CLASS_OR_NULL) { \
13131316
zend_wrong_parameter_string_or_class_or_null_error(_i, _error, _arg); \
1317+
} else if (_error_code == ZPP_ERROR_UNEXPECTED_EXTRA_NAMED) { \
1318+
zend_unexpected_extra_named_error(); \
13141319
} \
13151320
} \
13161321
failure; \
@@ -1707,11 +1712,31 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_value_error(uint32_t arg_num
17071712
dest = NULL; \
17081713
dest_num = 0; \
17091714
} \
1715+
if (UNEXPECTED(ZEND_CALL_INFO(execute_data) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { \
1716+
_error_code = ZPP_ERROR_UNEXPECTED_EXTRA_NAMED; \
1717+
break; \
1718+
} \
17101719
} while (0);
17111720

17121721
#define Z_PARAM_VARIADIC(spec, dest, dest_num) \
17131722
Z_PARAM_VARIADIC_EX(spec, dest, dest_num, 0)
17141723

1724+
#define Z_PARAM_VARIADIC_WITH_NAMED(spec, dest, dest_num, dest_named) do { \
1725+
int _num_varargs = _num_args - _i; \
1726+
if (EXPECTED(_num_varargs > 0)) { \
1727+
dest = _real_arg + 1; \
1728+
dest_num = _num_varargs; \
1729+
} else { \
1730+
dest = NULL; \
1731+
dest_num = 0; \
1732+
} \
1733+
if (ZEND_CALL_INFO(execute_data) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) { \
1734+
dest_named = execute_data->extra_named_params; \
1735+
} else { \
1736+
dest_named = NULL; \
1737+
} \
1738+
} while (0);
1739+
17151740
#define Z_PARAM_STR_OR_ARRAY_HT_EX(dest_str, dest_ht, allow_null) \
17161741
Z_PARAM_PROLOGUE(0, 0); \
17171742
if (UNEXPECTED(!zend_parse_arg_str_or_array_ht(_arg, &dest_str, &dest_ht, allow_null))) { \

0 commit comments

Comments
 (0)