Skip to content

Commit 513b767

Browse files
committed
Make zpp failures always throw, independent of strict_types
Previously zend_parse_parameters (and FastZPP) would handle invalid arguments depending on strict_types: With strict_types=1, a TypeError is thrown, with strict_types=0 a warning is thrown and (usually) NULL is returned. Additionally, some functions (constructors always and other methods sometimes) opt-it to throwing regardless of strict_types. This commit changes zpp to always generate a TypeError exception in PHP 8.
1 parent 87f8b1b commit 513b767

File tree

22 files changed

+67
-239
lines changed

22 files changed

+67
-239
lines changed

Zend/tests/004.phpt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ strncmp() tests
33
--FILE--
44
<?php
55

6-
var_dump(strncmp("", ""));
76
var_dump(strncmp("", "", 100));
87
var_dump(strncmp("aef", "dfsgbdf", -1));
98
var_dump(strncmp("fghjkl", "qwer", 0));
@@ -13,8 +12,6 @@ var_dump(strncmp("qwerty", "qwerty123", 7));
1312
echo "Done\n";
1413
?>
1514
--EXPECTF--
16-
Warning: strncmp() expects exactly 3 parameters, 2 given in %s on line %d
17-
NULL
1815
int(0)
1916

2017
Warning: Length must be greater than or equal to 0 in %s on line %d

Zend/tests/005.phpt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ strcasecmp() tests
33
--FILE--
44
<?php
55

6-
var_dump(strcasecmp(""));
76
var_dump(strcasecmp("", ""));
87
var_dump(strcasecmp("aef", "dfsgbdf"));
98
var_dump(strcasecmp("qwe", "qwer"));
@@ -15,8 +14,6 @@ var_dump(strcasecmp("01", "01"));
1514
echo "Done\n";
1615
?>
1716
--EXPECTF--
18-
Warning: strcasecmp() expects exactly 2 parameters, 1 given in %s on line %d
19-
NULL
2017
int(0)
2118
int(-3)
2219
int(-1)

Zend/tests/006.phpt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ strncasecmp() tests
33
--FILE--
44
<?php
55

6-
var_dump(strncasecmp(""));
76
var_dump(strncasecmp("", "", -1));
87
var_dump(strncasecmp("aef", "dfsgbdf", 0));
98
var_dump(strncasecmp("aef", "dfsgbdf", 10));
@@ -16,9 +15,6 @@ var_dump(strncasecmp("01", "01", 1000));
1615
echo "Done\n";
1716
?>
1817
--EXPECTF--
19-
Warning: strncasecmp() expects exactly 3 parameters, 1 given in %s on line %d
20-
NULL
21-
2218
Warning: Length must be greater than or equal to 0 in %s on line %d
2319
bool(false)
2420
int(0)

Zend/tests/008.phpt

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ define() tests
33
--FILE--
44
<?php
55

6-
var_dump(define());
7-
var_dump(define("TRUE"));
8-
var_dump(define("TRUE", 1));
9-
var_dump(define("TRUE", 1, array(1)));
6+
try {
7+
var_dump(define(array(1,2,3,4,5), 1));
8+
} catch (TypeError $e) {
9+
echo "TypeError: ", $e->getMessage(), "\n";
10+
}
1011

11-
var_dump(define(array(1,2,3,4,5), 1));
12+
var_dump(define("TRUE", 1));
1213
var_dump(define(" ", 1));
1314
var_dump(define("[[[", 2));
1415
var_dump(define("test const", 3));
@@ -24,20 +25,10 @@ var_dump(constant("test const"));
2425
echo "Done\n";
2526
?>
2627
--EXPECTF--
27-
Warning: define() expects at least 2 parameters, 0 given in %s on line %d
28-
NULL
29-
30-
Warning: define() expects at least 2 parameters, 1 given in %s on line %d
31-
NULL
28+
TypeError: define() expects parameter 1 to be string, array given
3229

3330
Notice: Constant TRUE already defined in %s on line %d
3431
bool(false)
35-
36-
Warning: define() expects parameter 3 to be bool, array given in %s on line %d
37-
NULL
38-
39-
Warning: define() expects parameter 1 to be string, array given in %s on line %d
40-
NULL
4132
bool(true)
4233
bool(true)
4334
bool(true)

Zend/zend.c

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1528,35 +1528,14 @@ ZEND_API ZEND_COLD void zend_type_error(const char *format, ...) /* {{{ */
15281528
va_end(va);
15291529
} /* }}} */
15301530

1531-
ZEND_API ZEND_COLD void zend_internal_type_error(zend_bool throw_exception, const char *format, ...) /* {{{ */
1531+
ZEND_API ZEND_COLD void zend_argument_count_error(const char *format, ...) /* {{{ */
15321532
{
15331533
va_list va;
15341534
char *message = NULL;
15351535

15361536
va_start(va, format);
15371537
zend_vspprintf(&message, 0, format, va);
1538-
if (throw_exception) {
1539-
zend_throw_exception(zend_ce_type_error, message, 0);
1540-
} else {
1541-
zend_error(E_WARNING, "%s", message);
1542-
}
1543-
efree(message);
1544-
1545-
va_end(va);
1546-
} /* }}} */
1547-
1548-
ZEND_API ZEND_COLD void zend_internal_argument_count_error(zend_bool throw_exception, const char *format, ...) /* {{{ */
1549-
{
1550-
va_list va;
1551-
char *message = NULL;
1552-
1553-
va_start(va, format);
1554-
zend_vspprintf(&message, 0, format, va);
1555-
if (throw_exception) {
1556-
zend_throw_exception(zend_ce_argument_count_error, message, 0);
1557-
} else {
1558-
zend_error(E_WARNING, "%s", message);
1559-
}
1538+
zend_throw_exception(zend_ce_argument_count_error, message, 0);
15601539
efree(message);
15611540

15621541
va_end(va);

Zend/zend.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,8 +303,7 @@ extern ZEND_API void (*zend_post_shutdown_cb)(void);
303303
ZEND_API ZEND_COLD void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
304304
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
305305
ZEND_API ZEND_COLD void zend_type_error(const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 1, 2);
306-
ZEND_API ZEND_COLD void zend_internal_type_error(zend_bool throw_exception, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
307-
ZEND_API ZEND_COLD void zend_internal_argument_count_error(zend_bool throw_exception, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
306+
ZEND_API ZEND_COLD void zend_argument_count_error(const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 1, 2);
308307

309308
ZEND_COLD void zenderror(const char *error);
310309

Zend/zend_API.c

Lines changed: 12 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ ZEND_API ZEND_COLD void zend_wrong_param_count(void) /* {{{ */
9090
const char *space;
9191
const char *class_name = get_active_class_name(&space);
9292

93-
zend_internal_argument_count_error(ZEND_ARG_USES_STRICT_TYPES(), "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name());
93+
zend_argument_count_error("Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name());
9494
}
9595
/* }}} */
9696

@@ -173,28 +173,7 @@ ZEND_API ZEND_COLD int ZEND_FASTCALL zend_wrong_parameters_none_error(void) /* {
173173
zend_function *active_function = EG(current_execute_data)->func;
174174
const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
175175

176-
zend_internal_argument_count_error(
177-
ZEND_ARG_USES_STRICT_TYPES(),
178-
"%s%s%s() expects %s %d parameter%s, %d given",
179-
class_name, \
180-
class_name[0] ? "::" : "", \
181-
ZSTR_VAL(active_function->common.function_name),
182-
"exactly",
183-
0,
184-
"s",
185-
num_args);
186-
return FAILURE;
187-
}
188-
/* }}} */
189-
190-
ZEND_API ZEND_COLD int ZEND_FASTCALL zend_wrong_parameters_none_exception(void) /* {{{ */
191-
{
192-
int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
193-
zend_function *active_function = EG(current_execute_data)->func;
194-
const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
195-
196-
zend_internal_argument_count_error(
197-
1,
176+
zend_argument_count_error(
198177
"%s%s%s() expects %s %d parameter%s, %d given",
199178
class_name, \
200179
class_name[0] ? "::" : "", \
@@ -213,27 +192,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_error(int min_
213192
zend_function *active_function = EG(current_execute_data)->func;
214193
const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
215194

216-
zend_internal_argument_count_error(
217-
ZEND_ARG_USES_STRICT_TYPES(),
218-
"%s%s%s() expects %s %d parameter%s, %d given",
219-
class_name, \
220-
class_name[0] ? "::" : "", \
221-
ZSTR_VAL(active_function->common.function_name),
222-
min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
223-
num_args < min_num_args ? min_num_args : max_num_args,
224-
(num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
225-
num_args);
226-
}
227-
/* }}} */
228-
229-
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_exception(int min_num_args, int max_num_args) /* {{{ */
230-
{
231-
int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
232-
zend_function *active_function = EG(current_execute_data)->func;
233-
const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
234-
235-
zend_internal_argument_count_error(
236-
1,
195+
zend_argument_count_error(
237196
"%s%s%s() expects %s %d parameter%s, %d given",
238197
class_name, \
239198
class_name[0] ? "::" : "", \
@@ -254,21 +213,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(int num, z
254213
NULL
255214
};
256215

257-
zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be %s, %s given",
258-
class_name, space, get_active_function_name(), num, expected_error[expected_type], zend_zval_type_name(arg));
259-
}
260-
/* }}} */
261-
262-
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_exception(int num, zend_expected_type expected_type, zval *arg) /* {{{ */
263-
{
264-
const char *space;
265-
const char *class_name = get_active_class_name(&space);
266-
static const char * const expected_error[] = {
267-
Z_EXPECTED_TYPES(Z_EXPECTED_TYPE_STR)
268-
NULL
269-
};
270-
271-
zend_internal_type_error(1, "%s%s%s() expects parameter %d to be %s, %s given",
216+
zend_type_error("%s%s%s() expects parameter %d to be %s, %s given",
272217
class_name, space, get_active_function_name(), num, expected_error[expected_type], zend_zval_type_name(arg));
273218
}
274219
/* }}} */
@@ -278,17 +223,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(int num,
278223
const char *space;
279224
const char *class_name = get_active_class_name(&space);
280225

281-
zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be %s, %s given",
282-
class_name, space, get_active_function_name(), num, name, zend_zval_type_name(arg));
283-
}
284-
/* }}} */
285-
286-
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_exception(int num, char *name, zval *arg) /* {{{ */
287-
{
288-
const char *space;
289-
const char *class_name = get_active_class_name(&space);
290-
291-
zend_internal_type_error(1, "%s%s%s() expects parameter %d to be %s, %s given",
226+
zend_type_error("%s%s%s() expects parameter %d to be %s, %s given",
292227
class_name, space, get_active_function_name(), num, name, zend_zval_type_name(arg));
293228
}
294229
/* }}} */
@@ -298,18 +233,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(int num, char *e
298233
const char *space;
299234
const char *class_name = get_active_class_name(&space);
300235

301-
zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a valid callback, %s",
302-
class_name, space, get_active_function_name(), num, error);
303-
efree(error);
304-
}
305-
/* }}} */
306-
307-
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, char *error) /* {{{ */
308-
{
309-
const char *space;
310-
const char *class_name = get_active_class_name(&space);
311-
312-
zend_internal_type_error(1, "%s%s%s() expects parameter %d to be a valid callback, %s",
236+
zend_type_error("%s%s%s() expects parameter %d to be a valid callback, %s",
313237
class_name, space, get_active_function_name(), num, error);
314238
efree(error);
315239
}
@@ -330,7 +254,7 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **pc
330254
const char *space;
331255
const char *class_name = get_active_class_name(&space);
332256

333-
zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a class name derived from %s, '%s' given",
257+
zend_type_error("%s%s%s() expects parameter %d to be a class name derived from %s, '%s' given",
334258
class_name, space, get_active_function_name(), num,
335259
ZSTR_VAL(ce_base->name), Z_STRVAL_P(arg));
336260
*pce = NULL;
@@ -341,7 +265,7 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **pc
341265
const char *space;
342266
const char *class_name = get_active_class_name(&space);
343267

344-
zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a valid class name, '%s' given",
268+
zend_type_error("%s%s%s() expects parameter %d to be a valid class name, '%s' given",
345269
class_name, space, get_active_function_name(), num,
346270
Z_STRVAL_P(arg));
347271
return 0;
@@ -803,16 +727,13 @@ static int zend_parse_arg(int arg_num, zval *arg, va_list *va, const char **spec
803727
if (!(flags & ZEND_PARSE_PARAMS_QUIET) && (*expected_type || error)) {
804728
const char *space;
805729
const char *class_name = get_active_class_name(&space);
806-
zend_bool throw_exception =
807-
ZEND_ARG_USES_STRICT_TYPES() || (flags & ZEND_PARSE_PARAMS_THROW);
808730

809731
if (error) {
810-
zend_internal_type_error(throw_exception, "%s%s%s() expects parameter %d %s",
732+
zend_type_error("%s%s%s() expects parameter %d %s",
811733
class_name, space, get_active_function_name(), arg_num, error);
812734
efree(error);
813735
} else {
814-
zend_internal_type_error(throw_exception,
815-
"%s%s%s() expects parameter %d to be %s, %s given",
736+
zend_type_error("%s%s%s() expects parameter %d to be %s, %s given",
816737
class_name, space, get_active_function_name(), arg_num, expected_type,
817738
zend_zval_type_name(arg));
818739
}
@@ -919,8 +840,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va,
919840
if (!(flags & ZEND_PARSE_PARAMS_QUIET)) {
920841
zend_function *active_function = EG(current_execute_data)->func;
921842
const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
922-
zend_bool throw_exception = ZEND_ARG_USES_STRICT_TYPES() || (flags & ZEND_PARSE_PARAMS_THROW);
923-
zend_internal_argument_count_error(throw_exception, "%s%s%s() expects %s %d parameter%s, %d given",
843+
zend_argument_count_error("%s%s%s() expects %s %d parameter%s, %d given",
924844
class_name,
925845
class_name[0] ? "::" : "",
926846
ZSTR_VAL(active_function->common.function_name),
@@ -1013,7 +933,7 @@ ZEND_API int zend_parse_parameters_throw(int num_args, const char *type_spec, ..
1013933
{
1014934
va_list va;
1015935
int retval;
1016-
int flags = ZEND_PARSE_PARAMS_THROW;
936+
int flags = 0;
1017937

1018938
va_start(va, type_spec);
1019939
retval = zend_parse_va_args(num_args, type_spec, &va, flags);

Zend/zend_API.h

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -248,12 +248,12 @@ ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array);
248248
#define zend_parse_parameters_none() \
249249
(EXPECTED(ZEND_NUM_ARGS() == 0) ? SUCCESS : zend_wrong_parameters_none_error())
250250
#define zend_parse_parameters_none_throw() \
251-
(EXPECTED(ZEND_NUM_ARGS() == 0) ? SUCCESS : zend_wrong_parameters_none_exception())
251+
zend_parse_parameters_none()
252252

253253
/* Parameter parsing API -- andrei */
254254

255+
#define ZEND_PARSE_PARAMS_THROW 0 /* No longer used, zpp always uses exceptions */
255256
#define ZEND_PARSE_PARAMS_QUIET (1<<1)
256-
#define ZEND_PARSE_PARAMS_THROW (1<<2)
257257
ZEND_API int zend_parse_parameters(int num_args, const char *type_spec, ...);
258258
ZEND_API int zend_parse_parameters_ex(int flags, int num_args, const char *type_spec, ...);
259259
ZEND_API int zend_parse_parameters_throw(int num_args, const char *type_spec, ...);
@@ -957,15 +957,10 @@ typedef enum _zend_expected_type {
957957
} zend_expected_type;
958958

959959
ZEND_API ZEND_COLD int ZEND_FASTCALL zend_wrong_parameters_none_error(void);
960-
ZEND_API ZEND_COLD int ZEND_FASTCALL zend_wrong_parameters_none_exception(void);
961960
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_error(int min_num_args, int max_num_args);
962-
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_exception(int min_num_args, int max_num_args);
963961
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(int num, zend_expected_type expected_type, zval *arg);
964-
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_exception(int num, zend_expected_type expected_type, zval *arg);
965962
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(int num, char *name, zval *arg);
966-
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_exception(int num, char *name, zval *arg);
967963
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(int num, char *error);
968-
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, char *error);
969964

970965
#define ZPP_ERROR_OK 0
971966
#define ZPP_ERROR_FAILURE 1
@@ -999,11 +994,7 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, cha
999994
(UNEXPECTED(_num_args > _max_num_args) && \
1000995
EXPECTED(_max_num_args >= 0))) { \
1001996
if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \
1002-
if (_flags & ZEND_PARSE_PARAMS_THROW) { \
1003-
zend_wrong_parameters_count_exception(_min_num_args, _max_num_args); \
1004-
} else { \
1005-
zend_wrong_parameters_count_error(_min_num_args, _max_num_args); \
1006-
} \
997+
zend_wrong_parameters_count_error(_min_num_args, _max_num_args); \
1007998
} \
1008999
_error_code = ZPP_ERROR_FAILURE; \
10091000
break; \
@@ -1026,23 +1017,11 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, cha
10261017
if (UNEXPECTED(_error_code != ZPP_ERROR_OK)) { \
10271018
if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \
10281019
if (_error_code == ZPP_ERROR_WRONG_CALLBACK) { \
1029-
if (_flags & ZEND_PARSE_PARAMS_THROW) { \
1030-
zend_wrong_callback_exception(_i, _error); \
1031-
} else { \
1032-
zend_wrong_callback_error(_i, _error); \
1033-
} \
1020+
zend_wrong_callback_error(_i, _error); \
10341021
} else if (_error_code == ZPP_ERROR_WRONG_CLASS) { \
1035-
if (_flags & ZEND_PARSE_PARAMS_THROW) { \
1036-
zend_wrong_parameter_class_exception(_i, _error, _arg); \
1037-
} else { \
1038-
zend_wrong_parameter_class_error(_i, _error, _arg); \
1039-
} \
1022+
zend_wrong_parameter_class_error(_i, _error, _arg); \
10401023
} else if (_error_code == ZPP_ERROR_WRONG_ARG) { \
1041-
if (_flags & ZEND_PARSE_PARAMS_THROW) { \
1042-
zend_wrong_parameter_type_exception(_i, _expected_type, _arg); \
1043-
} else { \
1044-
zend_wrong_parameter_type_error(_i, _expected_type, _arg); \
1045-
} \
1024+
zend_wrong_parameter_type_error(_i, _expected_type, _arg); \
10461025
} \
10471026
} \
10481027
failure; \

0 commit comments

Comments
 (0)