1573b4602SAndi Gutmans/*
2573b4602SAndi Gutmans   +----------------------------------------------------------------------+
3573b4602SAndi Gutmans   | Zend Engine                                                          |
4573b4602SAndi Gutmans   +----------------------------------------------------------------------+
5a6519d05SXinchen Hui   | Copyright (c) 1998-2018 Zend Technologies Ltd. (http://www.zend.com) |
6573b4602SAndi Gutmans   +----------------------------------------------------------------------+
7d863d52aSSebastian Bergmann   | This source file is subject to version 2.00 of the Zend license,     |
8d45250a0SMarcus Boerger   | that is bundled with this package in the file LICENSE, and is        |
9f68c7ff2SJames Cox   | available through the world-wide-web at the following url:           |
10d863d52aSSebastian Bergmann   | http://www.zend.com/license/2_00.txt.                                |
11b5b11177SZeev Suraski   | If you did not receive a copy of the Zend license and are unable to  |
12b5b11177SZeev Suraski   | obtain it through the world-wide-web, please send a note to          |
13b5b11177SZeev Suraski   | license@zend.com so we can mail you a copy immediately.              |
14573b4602SAndi Gutmans   +----------------------------------------------------------------------+
159afce019SZeev Suraski   | Authors: Andi Gutmans <andi@php.net>                                 |
169afce019SZeev Suraski   |          Zeev Suraski <zeev@php.net>                                 |
1758f88057SAndrei Zmievski   |          Andrei Zmievski <andrei@php.net>                            |
189afce019SZeev Suraski   |          Dmitry Stogov <dmitry@php.net>                              |
19573b4602SAndi Gutmans   +----------------------------------------------------------------------+
20573b4602SAndi Gutmans*/
21573b4602SAndi Gutmans
22573b4602SAndi Gutmans#include "zend.h"
23573b4602SAndi Gutmans#include "zend_execute.h"
24573b4602SAndi Gutmans#include "zend_API.h"
257080fa5bSAndi Gutmans#include "zend_modules.h"
2607b33992SXinchen Hui#include "zend_extensions.h"
27573b4602SAndi Gutmans#include "zend_constants.h"
2872692e9aSAaron Piotrowski#include "zend_interfaces.h"
29e8a8acdfSMarcus Boerger#include "zend_exceptions.h"
30d5ef2f46SDmitry Stogov#include "zend_closures.h"
31c343ca4eSNikita Popov#include "zend_inheritance.h"
32573b4602SAndi Gutmans
33009025e0SStig S. Bakken#ifdef HAVE_STDARG_H
3445835295SSascha Schumann#include <stdarg.h>
35573b4602SAndi Gutmans#endif
36573b4602SAndi Gutmans
37573b4602SAndi Gutmans/* these variables are true statics/globals, and have to be mutex'ed on every access */
382946f87fSAndi GutmansZEND_API HashTable module_registry;
39573b4602SAndi Gutmans
401a1178a6SDmitry Stogovstatic zend_module_entry **module_request_startup_handlers;
411a1178a6SDmitry Stogovstatic zend_module_entry **module_request_shutdown_handlers;
421a1178a6SDmitry Stogovstatic zend_module_entry **module_post_deactivate_handlers;
431a1178a6SDmitry Stogov
441a1178a6SDmitry Stogovstatic zend_class_entry  **class_cleanup_handlers;
451a1178a6SDmitry Stogov
46bdeb220fSAnatol BelskiZEND_API int _zend_get_parameters_array_ex(int param_count, zval *argument_array) /* {{{ */
4739f9487eSAndi Gutmans{
4843477bc7SDmitry Stogov	zval *param_ptr;
497a87fcbbSZeev Suraski	int arg_count;
5039f9487eSAndi Gutmans
51412ad4b2SDmitry Stogov	param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1);
5211384ba7SDmitry Stogov	arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
537a87fcbbSZeev Suraski
5439f9487eSAndi Gutmans	if (param_count>arg_count) {
5539f9487eSAndi Gutmans		return FAILURE;
5639f9487eSAndi Gutmans	}
5739f9487eSAndi Gutmans
58a2979141SZeev Suraski	while (param_count-->0) {
5943477bc7SDmitry Stogov		ZVAL_COPY_VALUE(argument_array, param_ptr);
60f4cfaf36SDmitry Stogov		argument_array++;
6143477bc7SDmitry Stogov		param_ptr++;
6239f9487eSAndi Gutmans	}
6339f9487eSAndi Gutmans
6439f9487eSAndi Gutmans	return SUCCESS;
6539f9487eSAndi Gutmans}
66b4892511SJani Taskinen/* }}} */
6739f9487eSAndi Gutmans
68bdeb220fSAnatol BelskiZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array) /* {{{ */
69e39f3f3fSMarcus Boerger{
7043477bc7SDmitry Stogov	zval *param_ptr;
71e39f3f3fSMarcus Boerger	int arg_count;
72e39f3f3fSMarcus Boerger
73412ad4b2SDmitry Stogov	param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1);
7411384ba7SDmitry Stogov	arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
75e39f3f3fSMarcus Boerger
76e39f3f3fSMarcus Boerger	if (param_count>arg_count) {
77e39f3f3fSMarcus Boerger		return FAILURE;
78e39f3f3fSMarcus Boerger	}
79e39f3f3fSMarcus Boerger
80e39f3f3fSMarcus Boerger	while (param_count-->0) {
81d56a534aSXinchen Hui		Z_TRY_ADDREF_P(param_ptr);
82c6978139SDmitry Stogov		zend_hash_next_index_insert_new(Z_ARRVAL_P(argument_array), param_ptr);
8343477bc7SDmitry Stogov		param_ptr++;
84e39f3f3fSMarcus Boerger	}
85e39f3f3fSMarcus Boerger
86e39f3f3fSMarcus Boerger	return SUCCESS;
87e39f3f3fSMarcus Boerger}
88b4892511SJani Taskinen/* }}} */
89e39f3f3fSMarcus Boerger
9071af54e5SDmitry StogovZEND_API ZEND_COLD void zend_wrong_param_count(void) /* {{{ */
918be4266fSAnthony Ferrara{
924a25a774SDmitry Stogov	const char *space;
93bdeb220fSAnatol Belski	const char *class_name = get_active_class_name(&space);
94b4892511SJani Taskinen
9512ee17d5SDavey Shafik	zend_internal_argument_count_error(ZEND_ARG_USES_STRICT_TYPES(), "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name());
96573b4602SAndi Gutmans}
97b4892511SJani Taskinen/* }}} */
9858f88057SAndrei Zmievski
9958f88057SAndrei Zmievski/* Argument parsing API -- andrei */
100b4892511SJani TaskinenZEND_API char *zend_get_type_by_const(int type) /* {{{ */
10158f88057SAndrei Zmievski{
1029dd24c6dSAntony Dovgal	switch(type) {
10317d027edSDmitry Stogov		case IS_FALSE:
10417d027edSDmitry Stogov		case IS_TRUE:
105c3c0f531SAndrea Faulds		case _IS_BOOL:
106fef879a2SGabriel Caruso			return "bool";
107c3e3c98eSAnatol Belski		case IS_LONG:
108ce1d69a1SGabriel Caruso			return "int";
10958f88057SAndrei Zmievski		case IS_DOUBLE:
110e5eb9530SAndrea Faulds			return "float";
11158f88057SAndrei Zmievski		case IS_STRING:
11258f88057SAndrei Zmievski			return "string";
11358f88057SAndrei Zmievski		case IS_OBJECT:
11458f88057SAndrei Zmievski			return "object";
11558f88057SAndrei Zmievski		case IS_RESOURCE:
11658f88057SAndrei Zmievski			return "resource";
1179dd24c6dSAntony Dovgal		case IS_NULL:
1189dd24c6dSAntony Dovgal			return "null";
119550980cfSHannes Magnusson		case IS_CALLABLE:
120550980cfSHannes Magnusson			return "callable";
121340a0000SAaron Piotrowski		case IS_ITERABLE:
122340a0000SAaron Piotrowski			return "iterable";
1239dd24c6dSAntony Dovgal		case IS_ARRAY:
1249dd24c6dSAntony Dovgal			return "array";
125366ba413SAndrea Faulds		case IS_VOID:
126366ba413SAndrea Faulds			return "void";
127b2b2b437SNikita Popov		case _IS_NUMBER:
128b2b2b437SNikita Popov			return "number";
12958f88057SAndrei Zmievski		default:
13058f88057SAndrei Zmievski			return "unknown";
13158f88057SAndrei Zmievski	}
13258f88057SAndrei Zmievski}
133b4892511SJani Taskinen/* }}} */
13458f88057SAndrei Zmievski
135cf7384aaSFelipe PenaZEND_API char *zend_zval_type_name(const zval *arg) /* {{{ */
1369dd24c6dSAntony Dovgal{
137c6cba554SDmitry Stogov	ZVAL_DEREF(arg);
1389dd24c6dSAntony Dovgal	return zend_get_type_by_const(Z_TYPE_P(arg));
1399dd24c6dSAntony Dovgal}
140b4892511SJani Taskinen/* }}} */
14158f88057SAndrei Zmievski
142f00d1c72SDmitry StogovZEND_API zend_string *zend_zval_get_type(const zval *arg) /* {{{ */
143f00d1c72SDmitry Stogov{
144f00d1c72SDmitry Stogov	switch (Z_TYPE_P(arg)) {
145f00d1c72SDmitry Stogov		case IS_NULL:
146f00d1c72SDmitry Stogov			return ZSTR_KNOWN(ZEND_STR_NULL);
147f00d1c72SDmitry Stogov		case IS_FALSE:
148f00d1c72SDmitry Stogov		case IS_TRUE:
149f00d1c72SDmitry Stogov			return ZSTR_KNOWN(ZEND_STR_BOOLEAN);
150f00d1c72SDmitry Stogov		case IS_LONG:
151f00d1c72SDmitry Stogov			return ZSTR_KNOWN(ZEND_STR_INTEGER);
152f00d1c72SDmitry Stogov		case IS_DOUBLE:
153f00d1c72SDmitry Stogov			return ZSTR_KNOWN(ZEND_STR_DOUBLE);
154f00d1c72SDmitry Stogov		case IS_STRING:
155f00d1c72SDmitry Stogov			return ZSTR_KNOWN(ZEND_STR_STRING);
156f00d1c72SDmitry Stogov		case IS_ARRAY:
157f00d1c72SDmitry Stogov			return ZSTR_KNOWN(ZEND_STR_ARRAY);
158f00d1c72SDmitry Stogov		case IS_OBJECT:
159f00d1c72SDmitry Stogov			return ZSTR_KNOWN(ZEND_STR_OBJECT);
160f00d1c72SDmitry Stogov		case IS_RESOURCE:
161f00d1c72SDmitry Stogov			if (zend_rsrc_list_get_rsrc_type(Z_RES_P(arg))) {
162f00d1c72SDmitry Stogov				return ZSTR_KNOWN(ZEND_STR_RESOURCE);
163f00d1c72SDmitry Stogov			} else {
164f00d1c72SDmitry Stogov				return ZSTR_KNOWN(ZEND_STR_CLOSED_RESOURCE);
165f00d1c72SDmitry Stogov			}
166f00d1c72SDmitry Stogov		default:
167f00d1c72SDmitry Stogov			return NULL;
168f00d1c72SDmitry Stogov	}
169f00d1c72SDmitry Stogov}
170f00d1c72SDmitry Stogov/* }}} */
171f00d1c72SDmitry Stogov
1727e329a82SDmitry StogovZEND_API ZEND_COLD int ZEND_FASTCALL zend_wrong_parameters_none_error(void) /* {{{ */
17327f38798SDmitry Stogov{
1747e329a82SDmitry Stogov	int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
17527f38798SDmitry Stogov	zend_function *active_function = EG(current_execute_data)->func;
1767aa76271SDmitry Stogov	const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
17727f38798SDmitry Stogov
17812ee17d5SDavey Shafik	zend_internal_argument_count_error(
1797e329a82SDmitry Stogov				ZEND_ARG_USES_STRICT_TYPES(),
1807e329a82SDmitry Stogov				"%s%s%s() expects %s %d parameter%s, %d given",
1817e329a82SDmitry Stogov				class_name, \
1827e329a82SDmitry Stogov				class_name[0] ? "::" : "", \
1837e329a82SDmitry Stogov				ZSTR_VAL(active_function->common.function_name),
1847e329a82SDmitry Stogov				"exactly",
1857e329a82SDmitry Stogov				0,
1867e329a82SDmitry Stogov				"s",
1877e329a82SDmitry Stogov				num_args);
1887e329a82SDmitry Stogov	return FAILURE;
1897e329a82SDmitry Stogov}
1907e329a82SDmitry Stogov/* }}} */
1917e329a82SDmitry Stogov
1927e329a82SDmitry StogovZEND_API ZEND_COLD int ZEND_FASTCALL zend_wrong_parameters_none_exception(void) /* {{{ */
1937e329a82SDmitry Stogov{
1947e329a82SDmitry Stogov	int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
1957e329a82SDmitry Stogov	zend_function *active_function = EG(current_execute_data)->func;
1967e329a82SDmitry Stogov	const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
1977e329a82SDmitry Stogov
1987e329a82SDmitry Stogov	zend_internal_argument_count_error(
1997e329a82SDmitry Stogov				1,
2007e329a82SDmitry Stogov				"%s%s%s() expects %s %d parameter%s, %d given",
2017e329a82SDmitry Stogov				class_name, \
2027e329a82SDmitry Stogov				class_name[0] ? "::" : "", \
2037e329a82SDmitry Stogov				ZSTR_VAL(active_function->common.function_name),
2047e329a82SDmitry Stogov				"exactly",
2057e329a82SDmitry Stogov				0,
2067e329a82SDmitry Stogov				"s",
2077e329a82SDmitry Stogov				num_args);
2087e329a82SDmitry Stogov	return FAILURE;
2097e329a82SDmitry Stogov}
2107e329a82SDmitry Stogov/* }}} */
2117e329a82SDmitry Stogov
2127e329a82SDmitry StogovZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_error(int min_num_args, int max_num_args) /* {{{ */
2137e329a82SDmitry Stogov{
2147e329a82SDmitry Stogov	int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
2157e329a82SDmitry Stogov	zend_function *active_function = EG(current_execute_data)->func;
2167e329a82SDmitry Stogov	const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
2177e329a82SDmitry Stogov
2187e329a82SDmitry Stogov	zend_internal_argument_count_error(
2197e329a82SDmitry Stogov				ZEND_ARG_USES_STRICT_TYPES(),
22064002648SGabriel Caruso				"%s%s%s() expects %s %d parameter%s, %d given",
22112ee17d5SDavey Shafik				class_name, \
22212ee17d5SDavey Shafik				class_name[0] ? "::" : "", \
22312ee17d5SDavey Shafik				ZSTR_VAL(active_function->common.function_name),
22412ee17d5SDavey Shafik				min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
22512ee17d5SDavey Shafik				num_args < min_num_args ? min_num_args : max_num_args,
22612ee17d5SDavey Shafik				(num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
22712ee17d5SDavey Shafik				num_args);
22827f38798SDmitry Stogov}
22927f38798SDmitry Stogov/* }}} */
23027f38798SDmitry Stogov
2317e329a82SDmitry StogovZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_exception(int min_num_args, int max_num_args) /* {{{ */
2327e329a82SDmitry Stogov{
2337e329a82SDmitry Stogov	int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
2347e329a82SDmitry Stogov	zend_function *active_function = EG(current_execute_data)->func;
2357e329a82SDmitry Stogov	const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
2367e329a82SDmitry Stogov
2377e329a82SDmitry Stogov	zend_internal_argument_count_error(
2387e329a82SDmitry Stogov				1,
2397e329a82SDmitry Stogov				"%s%s%s() expects %s %d parameter%s, %d given",
2407e329a82SDmitry Stogov				class_name, \
2417e329a82SDmitry Stogov				class_name[0] ? "::" : "", \
2427e329a82SDmitry Stogov				ZSTR_VAL(active_function->common.function_name),
2437e329a82SDmitry Stogov				min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
2447e329a82SDmitry Stogov				num_args < min_num_args ? min_num_args : max_num_args,
2457e329a82SDmitry Stogov				(num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
2467e329a82SDmitry Stogov				num_args);
2477e329a82SDmitry Stogov}
2487e329a82SDmitry Stogov/* }}} */
2497e329a82SDmitry Stogov
2507e329a82SDmitry StogovZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(int num, zend_expected_type expected_type, zval *arg) /* {{{ */
2517e329a82SDmitry Stogov{
2527e329a82SDmitry Stogov	const char *space;
2537e329a82SDmitry Stogov	const char *class_name = get_active_class_name(&space);
2547e329a82SDmitry Stogov	static const char * const expected_error[] = {
2567e329a82SDmitry Stogov		NULL
2577e329a82SDmitry Stogov	};
2587e329a82SDmitry Stogov
2597e329a82SDmitry Stogov	zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be %s, %s given",
2607e329a82SDmitry Stogov		class_name, space, get_active_function_name(), num, expected_error[expected_type], zend_zval_type_name(arg));
2617e329a82SDmitry Stogov}
2627e329a82SDmitry Stogov/* }}} */
2637e329a82SDmitry Stogov
2647e329a82SDmitry StogovZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_exception(int num, zend_expected_type expected_type, zval *arg) /* {{{ */
26527f38798SDmitry Stogov{
26627f38798SDmitry Stogov	const char *space;
267bdeb220fSAnatol Belski	const char *class_name = get_active_class_name(&space);
26827f38798SDmitry Stogov	static const char * const expected_error[] = {
27027f38798SDmitry Stogov		NULL
27127f38798SDmitry Stogov	};
27227f38798SDmitry Stogov
2737e329a82SDmitry Stogov	zend_internal_type_error(1, "%s%s%s() expects parameter %d to be %s, %s given",
274bdeb220fSAnatol Belski		class_name, space, get_active_function_name(), num, expected_error[expected_type], zend_zval_type_name(arg));
27527f38798SDmitry Stogov}
27627f38798SDmitry Stogov/* }}} */
27727f38798SDmitry Stogov
2787e329a82SDmitry StogovZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(int num, char *name, zval *arg) /* {{{ */
27927f38798SDmitry Stogov{
28027f38798SDmitry Stogov	const char *space;
281bdeb220fSAnatol Belski	const char *class_name = get_active_class_name(&space);
28227f38798SDmitry Stogov
2837e329a82SDmitry Stogov	zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be %s, %s given",
284bdeb220fSAnatol Belski		class_name, space, get_active_function_name(), num, name, zend_zval_type_name(arg));
28527f38798SDmitry Stogov}
28627f38798SDmitry Stogov/* }}} */
28727f38798SDmitry Stogov
2887e329a82SDmitry StogovZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_exception(int num, char *name, zval *arg) /* {{{ */
28927f38798SDmitry Stogov{
29027f38798SDmitry Stogov	const char *space;
291bdeb220fSAnatol Belski	const char *class_name = get_active_class_name(&space);
29227f38798SDmitry Stogov
2937e329a82SDmitry Stogov	zend_internal_type_error(1, "%s%s%s() expects parameter %d to be %s, %s given",
2947e329a82SDmitry Stogov		class_name, space, get_active_function_name(), num, name, zend_zval_type_name(arg));
2957e329a82SDmitry Stogov}
2967e329a82SDmitry Stogov/* }}} */
2977e329a82SDmitry Stogov
2987e329a82SDmitry StogovZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(int num, char *error) /* {{{ */
2997e329a82SDmitry Stogov{
3007e329a82SDmitry Stogov	const char *space;
3017e329a82SDmitry Stogov	const char *class_name = get_active_class_name(&space);
3027e329a82SDmitry Stogov
3037e329a82SDmitry Stogov	zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a valid callback, %s",
3047e329a82SDmitry Stogov		class_name, space, get_active_function_name(), num, error);
3057e329a82SDmitry Stogov	efree(error);
3067e329a82SDmitry Stogov}
3077e329a82SDmitry Stogov/* }}} */
3087e329a82SDmitry Stogov
3097e329a82SDmitry StogovZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, char *error) /* {{{ */
3107e329a82SDmitry Stogov{
3117e329a82SDmitry Stogov	const char *space;
3127e329a82SDmitry Stogov	const char *class_name = get_active_class_name(&space);
3137e329a82SDmitry Stogov
3147e329a82SDmitry Stogov	zend_internal_type_error(1, "%s%s%s() expects parameter %d to be a valid callback, %s",
3157e329a82SDmitry Stogov		class_name, space, get_active_function_name(), num, error);
3167e329a82SDmitry Stogov	efree(error);
3177e329a82SDmitry Stogov}
3187e329a82SDmitry Stogov/* }}} */
3197e329a82SDmitry Stogov
3207e329a82SDmitry StogovZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_deprecated(int num, char *error) /* {{{ */
3217e329a82SDmitry Stogov{
3227e329a82SDmitry Stogov	const char *space;
3237e329a82SDmitry Stogov	const char *class_name = get_active_class_name(&space);
3247e329a82SDmitry Stogov
3257e329a82SDmitry Stogov	zend_error(E_DEPRECATED, "%s%s%s() expects parameter %d to be a valid callback, %s",
3267e329a82SDmitry Stogov		class_name, space, get_active_function_name(), num, error);
32727f38798SDmitry Stogov	efree(error);
32827f38798SDmitry Stogov}
32927f38798SDmitry Stogov/* }}} */
33027f38798SDmitry Stogov
33135f9b90bSDmitry StogovZEND_API int ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **pce, int num, int check_null) /* {{{ */
33227f38798SDmitry Stogov{
33327f38798SDmitry Stogov	zend_class_entry *ce_base = *pce;
33427f38798SDmitry Stogov
33527f38798SDmitry Stogov	if (check_null && Z_TYPE_P(arg) == IS_NULL) {
33627f38798SDmitry Stogov		*pce = NULL;
33727f38798SDmitry Stogov		return 1;
33827f38798SDmitry Stogov	}
33927f38798SDmitry Stogov	convert_to_string_ex(arg);
340bdeb220fSAnatol Belski	*pce = zend_lookup_class(Z_STR_P(arg));
34127f38798SDmitry Stogov	if (ce_base) {
342bdeb220fSAnatol Belski		if ((!*pce || !instanceof_function(*pce, ce_base))) {
34327f38798SDmitry Stogov			const char *space;
344bdeb220fSAnatol Belski			const char *class_name = get_active_class_name(&space);
34527f38798SDmitry Stogov
34635f9b90bSDmitry Stogov			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",
347bdeb220fSAnatol Belski				class_name, space, get_active_function_name(), num,
3487aa76271SDmitry Stogov				ZSTR_VAL(ce_base->name), Z_STRVAL_P(arg));
34927f38798SDmitry Stogov			*pce = NULL;
35027f38798SDmitry Stogov			return 0;
35127f38798SDmitry Stogov		}
35227f38798SDmitry Stogov	}
35327f38798SDmitry Stogov	if (!*pce) {
35427f38798SDmitry Stogov		const char *space;
355bdeb220fSAnatol Belski		const char *class_name = get_active_class_name(&space);
35627f38798SDmitry Stogov
35735f9b90bSDmitry Stogov		zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a valid class name, '%s' given",
358bdeb220fSAnatol Belski			class_name, space, get_active_function_name(), num,
35927f38798SDmitry Stogov			Z_STRVAL_P(arg));
36027f38798SDmitry Stogov		return 0;
36127f38798SDmitry Stogov	}
36227f38798SDmitry Stogov	return 1;
36327f38798SDmitry Stogov}
36427f38798SDmitry Stogov/* }}} */
36527f38798SDmitry Stogov
36635f9b90bSDmitry StogovZEND_API int ZEND_FASTCALL zend_parse_arg_bool_weak(zval *arg, zend_bool *dest) /* {{{ */
36735f9b90bSDmitry Stogov{
36835f9b90bSDmitry Stogov	if (EXPECTED(Z_TYPE_P(arg) <= IS_STRING)) {
36935f9b90bSDmitry Stogov		*dest = zend_is_true(arg);
37035f9b90bSDmitry Stogov	} else {
37135f9b90bSDmitry Stogov		return 0;
37235f9b90bSDmitry Stogov	}
37335f9b90bSDmitry Stogov	return 1;
37435f9b90bSDmitry Stogov}
37535f9b90bSDmitry Stogov/* }}} */
37635f9b90bSDmitry Stogov
37735f9b90bSDmitry StogovZEND_API int ZEND_FASTCALL zend_parse_arg_bool_slow(zval *arg, zend_bool *dest) /* {{{ */
37835f9b90bSDmitry Stogov{
37935f9b90bSDmitry Stogov	if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
38035f9b90bSDmitry Stogov		return 0;
38135f9b90bSDmitry Stogov	}
38235f9b90bSDmitry Stogov	return zend_parse_arg_bool_weak(arg, dest);
38335f9b90bSDmitry Stogov}
38435f9b90bSDmitry Stogov/* }}} */
38535f9b90bSDmitry Stogov
38635f9b90bSDmitry StogovZEND_API int ZEND_FASTCALL zend_parse_arg_long_weak(zval *arg, zend_long *dest) /* {{{ */
38735f9b90bSDmitry Stogov{
38835f9b90bSDmitry Stogov	if (EXPECTED(Z_TYPE_P(arg) == IS_DOUBLE)) {
38935f9b90bSDmitry Stogov		if (UNEXPECTED(zend_isnan(Z_DVAL_P(arg)))) {
39035f9b90bSDmitry Stogov			return 0;
39135f9b90bSDmitry Stogov		}
39235f9b90bSDmitry Stogov		if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(Z_DVAL_P(arg)))) {
39335f9b90bSDmitry Stogov			return 0;
39435f9b90bSDmitry Stogov		} else {
39535f9b90bSDmitry Stogov			*dest = zend_dval_to_lval(Z_DVAL_P(arg));
39635f9b90bSDmitry Stogov		}
39735f9b90bSDmitry Stogov	} else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
39835f9b90bSDmitry Stogov		double d;
39935f9b90bSDmitry Stogov		int type;
40035f9b90bSDmitry Stogov
40135f9b90bSDmitry Stogov		if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), dest, &d)) != IS_LONG)) {
40235f9b90bSDmitry Stogov			if (EXPECTED(type != 0)) {
40335f9b90bSDmitry Stogov				if (UNEXPECTED(zend_isnan(d))) {
40435f9b90bSDmitry Stogov					return 0;
40535f9b90bSDmitry Stogov				}
40635f9b90bSDmitry Stogov				if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(d))) {
40735f9b90bSDmitry Stogov					return 0;
40835f9b90bSDmitry Stogov				} else {
40935f9b90bSDmitry Stogov					*dest = zend_dval_to_lval(d);
41035f9b90bSDmitry Stogov				}
41135f9b90bSDmitry Stogov			} else {
41235f9b90bSDmitry Stogov				return 0;
41335f9b90bSDmitry Stogov			}
41435f9b90bSDmitry Stogov		}
41535f9b90bSDmitry Stogov	} else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
41635f9b90bSDmitry Stogov		*dest = 0;
41735f9b90bSDmitry Stogov	} else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
41835f9b90bSDmitry Stogov		*dest = 1;
41935f9b90bSDmitry Stogov	} else {
42035f9b90bSDmitry Stogov		return 0;
42135f9b90bSDmitry Stogov	}
42235f9b90bSDmitry Stogov	return 1;
42335f9b90bSDmitry Stogov}
42435f9b90bSDmitry Stogov/* }}} */
42535f9b90bSDmitry Stogov
42635f9b90bSDmitry StogovZEND_API int ZEND_FASTCALL zend_parse_arg_long_slow(zval *arg, zend_long *dest) /* {{{ */
42735f9b90bSDmitry Stogov{
42835f9b90bSDmitry Stogov	if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
42935f9b90bSDmitry Stogov		return 0;
43035f9b90bSDmitry Stogov	}
43135f9b90bSDmitry Stogov	return zend_parse_arg_long_weak(arg, dest);
43235f9b90bSDmitry Stogov}
43335f9b90bSDmitry Stogov/* }}} */
43435f9b90bSDmitry Stogov
43535f9b90bSDmitry StogovZEND_API int ZEND_FASTCALL zend_parse_arg_long_cap_weak(zval *arg, zend_long *dest) /* {{{ */
43635f9b90bSDmitry Stogov{
43735f9b90bSDmitry Stogov	if (EXPECTED(Z_TYPE_P(arg) == IS_DOUBLE)) {
43835f9b90bSDmitry Stogov		if (UNEXPECTED(zend_isnan(Z_DVAL_P(arg)))) {
43935f9b90bSDmitry Stogov			return 0;
44035f9b90bSDmitry Stogov		}
4411e82ad80SAndrea Faulds		*dest = zend_dval_to_lval_cap(Z_DVAL_P(arg));
44235f9b90bSDmitry Stogov	} else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
44335f9b90bSDmitry Stogov		double d;
44435f9b90bSDmitry Stogov		int type;
44535f9b90bSDmitry Stogov
44635f9b90bSDmitry Stogov		if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), dest, &d)) != IS_LONG)) {
44735f9b90bSDmitry Stogov			if (EXPECTED(type != 0)) {
44835f9b90bSDmitry Stogov				if (UNEXPECTED(zend_isnan(d))) {
44935f9b90bSDmitry Stogov					return 0;
45035f9b90bSDmitry Stogov				}
4511e82ad80SAndrea Faulds				*dest = zend_dval_to_lval_cap(d);
45235f9b90bSDmitry Stogov			} else {
45335f9b90bSDmitry Stogov				return 0;
45435f9b90bSDmitry Stogov			}
45535f9b90bSDmitry Stogov		}
45635f9b90bSDmitry Stogov	} else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
45735f9b90bSDmitry Stogov		*dest = 0;
45835f9b90bSDmitry Stogov	} else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
45935f9b90bSDmitry Stogov		*dest = 1;
46035f9b90bSDmitry Stogov	} else {
46135f9b90bSDmitry Stogov		return 0;
46235f9b90bSDmitry Stogov	}
46335f9b90bSDmitry Stogov	return 1;
46435f9b90bSDmitry Stogov}
46535f9b90bSDmitry Stogov/* }}} */
46635f9b90bSDmitry Stogov
46735f9b90bSDmitry StogovZEND_API int ZEND_FASTCALL zend_parse_arg_long_cap_slow(zval *arg, zend_long *dest) /* {{{ */
46835f9b90bSDmitry Stogov{
46935f9b90bSDmitry Stogov	if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
47035f9b90bSDmitry Stogov		return 0;
47135f9b90bSDmitry Stogov	}
47235f9b90bSDmitry Stogov	return zend_parse_arg_long_cap_weak(arg, dest);
47335f9b90bSDmitry Stogov}
47435f9b90bSDmitry Stogov/* }}} */
47535f9b90bSDmitry Stogov
47635f9b90bSDmitry StogovZEND_API int ZEND_FASTCALL zend_parse_arg_double_weak(zval *arg, double *dest) /* {{{ */
47735f9b90bSDmitry Stogov{
47835f9b90bSDmitry Stogov	if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
47935f9b90bSDmitry Stogov		*dest = (double)Z_LVAL_P(arg);
48035f9b90bSDmitry Stogov	} else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
48135f9b90bSDmitry Stogov		zend_long l;
48235f9b90bSDmitry Stogov		int type;
48335f9b90bSDmitry Stogov
48435f9b90bSDmitry Stogov		if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), &l, dest)) != IS_DOUBLE)) {
48535f9b90bSDmitry Stogov			if (EXPECTED(type != 0)) {
48635f9b90bSDmitry Stogov				*dest = (double)(l);
48735f9b90bSDmitry Stogov			} else {
48835f9b90bSDmitry Stogov				return 0;
48935f9b90bSDmitry Stogov			}
49035f9b90bSDmitry Stogov		}
49135f9b90bSDmitry Stogov	} else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
49235f9b90bSDmitry Stogov		*dest = 0.0;
49335f9b90bSDmitry Stogov	} else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
49435f9b90bSDmitry Stogov		*dest = 1.0;
49535f9b90bSDmitry Stogov	} else {
49635f9b90bSDmitry Stogov		return 0;
49735f9b90bSDmitry Stogov	}
49835f9b90bSDmitry Stogov	return 1;
49935f9b90bSDmitry Stogov}
50035f9b90bSDmitry Stogov/* }}} */
50135f9b90bSDmitry Stogov
50235f9b90bSDmitry StogovZEND_API int ZEND_FASTCALL zend_parse_arg_double_slow(zval *arg, double *dest) /* {{{ */
50335f9b90bSDmitry Stogov{
50435f9b90bSDmitry Stogov	if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
50535f9b90bSDmitry Stogov		/* SSTH Exception: IS_LONG may be accepted instead as IS_DOUBLE */
50635f9b90bSDmitry Stogov		*dest = (double)Z_LVAL_P(arg);
50735f9b90bSDmitry Stogov	} else if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
50835f9b90bSDmitry Stogov		return 0;
50935f9b90bSDmitry Stogov	}
51035f9b90bSDmitry Stogov	return zend_parse_arg_double_weak(arg, dest);
51135f9b90bSDmitry Stogov}
51235f9b90bSDmitry Stogov/* }}} */
51335f9b90bSDmitry Stogov
51435f9b90bSDmitry StogovZEND_API int ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest) /* {{{ */
51535f9b90bSDmitry Stogov{
51635f9b90bSDmitry Stogov	if (EXPECTED(Z_TYPE_P(arg) < IS_STRING)) {
51735f9b90bSDmitry Stogov		convert_to_string(arg);
51835f9b90bSDmitry Stogov		*dest = Z_STR_P(arg);
51935f9b90bSDmitry Stogov	} else if (UNEXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
52035f9b90bSDmitry Stogov		if (Z_OBJ_HANDLER_P(arg, cast_object)) {
52135f9b90bSDmitry Stogov			zval obj;
52235f9b90bSDmitry Stogov			if (Z_OBJ_HANDLER_P(arg, cast_object)(arg, &obj, IS_STRING) == SUCCESS) {
52335f9b90bSDmitry Stogov				zval_ptr_dtor(arg);
52435f9b90bSDmitry Stogov				ZVAL_COPY_VALUE(arg, &obj);
52535f9b90bSDmitry Stogov				*dest = Z_STR_P(arg);
52635f9b90bSDmitry Stogov				return 1;
52735f9b90bSDmitry Stogov			}
528628d4394SNikita Popov		} else if (Z_OBJ_HANDLER_P(arg, get)) {
52935f9b90bSDmitry Stogov			zval rv;
53035f9b90bSDmitry Stogov			zval *z = Z_OBJ_HANDLER_P(arg, get)(arg, &rv);
53135f9b90bSDmitry Stogov
53235f9b90bSDmitry Stogov			if (Z_TYPE_P(z) != IS_OBJECT) {
53341db5f73SDmitry Stogov				zval_ptr_dtor(arg);
53441db5f73SDmitry Stogov				if (Z_TYPE_P(z) == IS_STRING) {
5358e10e8f9SDmitry Stogov					ZVAL_COPY_VALUE(arg, z);
53641db5f73SDmitry Stogov				} else {
53741db5f73SDmitry Stogov					ZVAL_STR(arg, zval_get_string_func(z));
53841db5f73SDmitry Stogov					zval_ptr_dtor(z);
53935f9b90bSDmitry Stogov				}
54035f9b90bSDmitry Stogov				*dest = Z_STR_P(arg);
54135f9b90bSDmitry Stogov				return 1;
54235f9b90bSDmitry Stogov			}
54335f9b90bSDmitry Stogov			zval_ptr_dtor(z);
54435f9b90bSDmitry Stogov		}
54535f9b90bSDmitry Stogov		return 0;
54635f9b90bSDmitry Stogov	} else {
54735f9b90bSDmitry Stogov		return 0;
54835f9b90bSDmitry Stogov	}
54935f9b90bSDmitry Stogov	return 1;
55035f9b90bSDmitry Stogov}
55135f9b90bSDmitry Stogov/* }}} */
55235f9b90bSDmitry Stogov
55335f9b90bSDmitry StogovZEND_API int ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, zend_string **dest) /* {{{ */
55435f9b90bSDmitry Stogov{
55535f9b90bSDmitry Stogov	if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
55635f9b90bSDmitry Stogov		return 0;
55735f9b90bSDmitry Stogov	}
55835f9b90bSDmitry Stogov	return zend_parse_arg_str_weak(arg, dest);
55935f9b90bSDmitry Stogov}
56035f9b90bSDmitry Stogov/* }}} */
56135f9b90bSDmitry Stogov
56235f9b90bSDmitry Stogovstatic const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, const char **spec, char **error, int *severity) /* {{{ */
56358f88057SAndrei Zmievski{
564aaa2f1c3SHartmut Holzgraefe	const char *spec_walk = *spec;
56558f88057SAndrei Zmievski	char c = *spec_walk++;
566980dc711SGustavo André dos Santos Lopes	int check_null = 0;
56742184397SDmitry Stogov	int separate = 0;
5688bae1daaSDmitry Stogov	zval *real_arg = arg;
56958f88057SAndrei Zmievski
570b4892511SJani Taskinen	/* scan through modifiers */
571c1965f58SDmitry Stogov	ZVAL_DEREF(arg);
572b4892511SJani Taskinen	while (1) {
57358f88057SAndrei Zmievski		if (*spec_walk == '/') {
574560e4fa3SDmitry Stogov			SEPARATE_ZVAL_NOREF(arg);
575c1965f58SDmitry Stogov			real_arg = arg;
57642184397SDmitry Stogov			separate = 1;
577b4892511SJani Taskinen		} else if (*spec_walk == '!') {
578980dc711SGustavo André dos Santos Lopes			check_null = 1;
579b4892511SJani Taskinen		} else {
580b4892511SJani Taskinen			break;
58158f88057SAndrei Zmievski		}
58258f88057SAndrei Zmievski		spec_walk++;
58358f88057SAndrei Zmievski	}
58458f88057SAndrei Zmievski
58558f88057SAndrei Zmievski	switch (c) {
58658f88057SAndrei Zmievski		case 'l':
587b907aa43SMatt Wilmas		case 'L':
58858f88057SAndrei Zmievski			{
589c3e3c98eSAnatol Belski				zend_long *p = va_arg(*va, zend_long *);
59041e3fdbaSAndrea Faulds				zend_bool *is_null = NULL;
591980dc711SGustavo André dos Santos Lopes
592980dc711SGustavo André dos Santos Lopes				if (check_null) {
59341e3fdbaSAndrea Faulds					is_null = va_arg(*va, zend_bool *);
594980dc711SGustavo André dos Santos Lopes				}
595980dc711SGustavo André dos Santos Lopes
59635f9b90bSDmitry Stogov				if (!zend_parse_arg_long(arg, p, is_null, check_null, c == 'L')) {
597ce1d69a1SGabriel Caruso					return "int";
59858f88057SAndrei Zmievski				}
59958f88057SAndrei Zmievski			}
60058f88057SAndrei Zmievski			break;
60158f88057SAndrei Zmievski
60258f88057SAndrei Zmievski		case 'd':
60358f88057SAndrei Zmievski			{
60458f88057SAndrei Zmievski				double *p = va_arg(*va, double *);
60541e3fdbaSAndrea Faulds				zend_bool *is_null = NULL;
606980dc711SGustavo André dos Santos Lopes
607980dc711SGustavo André dos Santos Lopes				if (check_null) {
60841e3fdbaSAndrea Faulds					is_null = va_arg(*va, zend_bool *);
609980dc711SGustavo André dos Santos Lopes				}
610980dc711SGustavo André dos Santos Lopes
61135f9b90bSDmitry Stogov				if (!zend_parse_arg_double(arg, p, is_null, check_null)) {
61241e3fdbaSAndrea Faulds					return "float";
61358f88057SAndrei Zmievski				}
61458f88057SAndrei Zmievski			}
61558f88057SAndrei Zmievski			break;
61658f88057SAndrei Zmievski
61758f88057SAndrei Zmievski		case 's':
61858f88057SAndrei Zmievski			{
61958f88057SAndrei Zmievski				char **p = va_arg(*va, char **);
62032344808SAnatol Belski				size_t *pl = va_arg(*va, size_t *);
62135f9b90bSDmitry Stogov				if (!zend_parse_arg_string(arg, p, pl, check_null)) {
62241e3fdbaSAndrea Faulds					return "string";
62341e3fdbaSAndrea Faulds				}
62441e3fdbaSAndrea Faulds			}
62541e3fdbaSAndrea Faulds			break;
626b7a7b1a6SStanislav Malyshev
62741e3fdbaSAndrea Faulds		case 'p':
62841e3fdbaSAndrea Faulds			{
62941e3fdbaSAndrea Faulds				char **p = va_arg(*va, char **);
63041e3fdbaSAndrea Faulds				size_t *pl = va_arg(*va, size_t *);
63135f9b90bSDmitry Stogov				if (!zend_parse_arg_path(arg, p, pl, check_null)) {
63241e3fdbaSAndrea Faulds					return "a valid path";
63358f88057SAndrei Zmievski				}
63458f88057SAndrei Zmievski			}
63558f88057SAndrei Zmievski			break;
63658f88057SAndrei Zmievski
637bea30846SXinchen Hui		case 'P':
63841e3fdbaSAndrea Faulds			{
63941e3fdbaSAndrea Faulds				zend_string **str = va_arg(*va, zend_string **);
64035f9b90bSDmitry Stogov				if (!zend_parse_arg_path_str(arg, str, check_null)) {
64141e3fdbaSAndrea Faulds					return "a valid path";
64241e3fdbaSAndrea Faulds				}
64341e3fdbaSAndrea Faulds			}
64441e3fdbaSAndrea Faulds			break;
64541e3fdbaSAndrea Faulds
646f4cfaf36SDmitry Stogov		case 'S':
647f4cfaf36SDmitry Stogov			{
648f4cfaf36SDmitry Stogov				zend_string **str = va_arg(*va, zend_string **);
64935f9b90bSDmitry Stogov				if (!zend_parse_arg_str(arg, str, check_null)) {
65041e3fdbaSAndrea Faulds					return "string";
651f4cfaf36SDmitry Stogov				}
652f4cfaf36SDmitry Stogov			}
653f4cfaf36SDmitry Stogov			break;
654f4cfaf36SDmitry Stogov
65558f88057SAndrei Zmievski		case 'b':
65658f88057SAndrei Zmievski			{
65758f88057SAndrei Zmievski				zend_bool *p = va_arg(*va, zend_bool *);
65841e3fdbaSAndrea Faulds				zend_bool *is_null = NULL;
659980dc711SGustavo André dos Santos Lopes
660980dc711SGustavo André dos Santos Lopes				if (check_null) {
66141e3fdbaSAndrea Faulds					is_null = va_arg(*va, zend_bool *);
662980dc711SGustavo André dos Santos Lopes				}
663980dc711SGustavo André dos Santos Lopes
66435f9b90bSDmitry Stogov				if (!zend_parse_arg_bool(arg, p, is_null, check_null)) {
665fef879a2SGabriel Caruso					return "bool";
66658f88057SAndrei Zmievski				}
66758f88057SAndrei Zmievski			}
66858f88057SAndrei Zmievski			break;
66958f88057SAndrei Zmievski
67058f88057SAndrei Zmievski		case 'r':
67158f88057SAndrei Zmievski			{
67258f88057SAndrei Zmievski				zval **p = va_arg(*va, zval **);
67341e3fdbaSAndrea Faulds
67441e3fdbaSAndrea Faulds				if (!zend_parse_arg_resource(arg, p, check_null)) {
675b4892511SJani Taskinen					return "resource";
676637a4042SMarcus Boerger				}
67758f88057SAndrei Zmievski			}
67858f88057SAndrei Zmievski			break;
67941e3fdbaSAndrea Faulds
680fce39ed9SStanislav Malyshev		case 'A':
68158f88057SAndrei Zmievski		case 'a':
68258f88057SAndrei Zmievski			{
68358f88057SAndrei Zmievski				zval **p = va_arg(*va, zval **);
68441e3fdbaSAndrea Faulds
68541e3fdbaSAndrea Faulds				if (!zend_parse_arg_array(arg, p, check_null, c == 'A')) {
686b4892511SJani Taskinen					return "array";
687637a4042SMarcus Boerger				}
68858f88057SAndrei Zmievski			}
68958f88057SAndrei Zmievski			break;
69041e3fdbaSAndrea Faulds
691fce39ed9SStanislav Malyshev		case 'H':
69277915bc2SMarcus Boerger		case 'h':
69377915bc2SMarcus Boerger			{
69477915bc2SMarcus Boerger				HashTable **p = va_arg(*va, HashTable **);
69541e3fdbaSAndrea Faulds
69642184397SDmitry Stogov				if (!zend_parse_arg_array_ht(arg, p, check_null, c == 'H', separate)) {
697b4892511SJani Taskinen					return "array";
69877915bc2SMarcus Boerger				}
69977915bc2SMarcus Boerger			}
70077915bc2SMarcus Boerger			break;
70177915bc2SMarcus Boerger
70258f88057SAndrei Zmievski		case 'o':
70358f88057SAndrei Zmievski			{
70458f88057SAndrei Zmievski				zval **p = va_arg(*va, zval **);
70541e3fdbaSAndrea Faulds
70641e3fdbaSAndrea Faulds				if (!zend_parse_arg_object(arg, p, NULL, check_null)) {
707b4892511SJani Taskinen					return "object";
708637a4042SMarcus Boerger				}
70958f88057SAndrei Zmievski			}
71058f88057SAndrei Zmievski			break;
71158f88057SAndrei Zmievski
71258f88057SAndrei Zmievski		case 'O':
71358f88057SAndrei Zmievski			{
71458f88057SAndrei Zmievski				zval **p = va_arg(*va, zval **);
71558f88057SAndrei Zmievski				zend_class_entry *ce = va_arg(*va, zend_class_entry *);
7165c4de266SWez Furlong
71741e3fdbaSAndrea Faulds				if (!zend_parse_arg_object(arg, p, ce, check_null)) {
718b4892511SJani Taskinen					if (ce) {
7197aa76271SDmitry Stogov						return ZSTR_VAL(ce->name);
72058f88057SAndrei Zmievski					} else {
721ca6a2021SMarcus Boerger						return "object";
72258f88057SAndrei Zmievski					}
7235c4de266SWez Furlong				}
72458f88057SAndrei Zmievski			}
72558f88057SAndrei Zmievski			break;
72658f88057SAndrei Zmievski
7272e37e863SMarcus Boerger		case 'C':
7282e37e863SMarcus Boerger			{
729f4cfaf36SDmitry Stogov				zend_class_entry *lookup, **pce = va_arg(*va, zend_class_entry **);
7302e37e863SMarcus Boerger				zend_class_entry *ce_base = *pce;
7312e37e863SMarcus Boerger
732f4cfaf36SDmitry Stogov				if (check_null && Z_TYPE_P(arg) == IS_NULL) {
733f88a1729SMarcus Boerger					*pce = NULL;
734f88a1729SMarcus Boerger					break;
735f88a1729SMarcus Boerger				}
7362e37e863SMarcus Boerger				convert_to_string_ex(arg);
737bdeb220fSAnatol Belski				if ((lookup = zend_lookup_class(Z_STR_P(arg))) == NULL) {
7382e37e863SMarcus Boerger					*pce = NULL;
7392e37e863SMarcus Boerger				} else {
740f4cfaf36SDmitry Stogov					*pce = lookup;
7412e37e863SMarcus Boerger				}
7422e37e863SMarcus Boerger				if (ce_base) {
743bdeb220fSAnatol Belski					if ((!*pce || !instanceof_function(*pce, ce_base))) {
744e8a8acdfSMarcus Boerger						zend_spprintf(error, 0, "to be a class name derived from %s, '%s' given",
7457aa76271SDmitry Stogov							ZSTR_VAL(ce_base->name), Z_STRVAL_P(arg));
7462e37e863SMarcus Boerger						*pce = NULL;
7472e37e863SMarcus Boerger						return "";
7482e37e863SMarcus Boerger					}
7492e37e863SMarcus Boerger				}
750f88a1729SMarcus Boerger				if (!*pce) {
751e8a8acdfSMarcus Boerger					zend_spprintf(error, 0, "to be a valid class name, '%s' given",
752f4cfaf36SDmitry Stogov						Z_STRVAL_P(arg));
7532e37e863SMarcus Boerger					return "";
7542e37e863SMarcus Boerger				}
7552e37e863SMarcus Boerger				break;
7562e37e863SMarcus Boerger
7572e37e863SMarcus Boerger			}
7582e37e863SMarcus Boerger			break;
7592e37e863SMarcus Boerger
76064c353abSMarcus Boerger		case 'f':
76164c353abSMarcus Boerger			{
762b4892511SJani Taskinen				zend_fcall_info *fci = va_arg(*va, zend_fcall_info *);
76364c353abSMarcus Boerger				zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *);
764e8a8acdfSMarcus Boerger				char *is_callable_error = NULL;
76564c353abSMarcus Boerger
766f4cfaf36SDmitry Stogov				if (check_null && Z_TYPE_P(arg) == IS_NULL) {
76764c353abSMarcus Boerger					fci->size = 0;
768d9f5ea69SDmitry Stogov					fcc->function_handler = 0;
76964c353abSMarcus Boerger					break;
770b4892511SJani Taskinen				}
771b4892511SJani Taskinen
772bdeb220fSAnatol Belski				if (zend_fcall_info_init(arg, 0, fci, fcc, NULL, &is_callable_error) == SUCCESS) {
773e8a8acdfSMarcus Boerger					if (is_callable_error) {
7748d003858SNikita Popov						*severity = E_DEPRECATED;
775a50e9d87SNikita Popov						zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error);
776e8a8acdfSMarcus Boerger						efree(is_callable_error);
777ac8e76c7SMarcus Boerger						*spec = spec_walk;
778e8a8acdfSMarcus Boerger						return "";
779e8a8acdfSMarcus Boerger					}
780b4892511SJani Taskinen					break;
78164c353abSMarcus Boerger				} else {
782e8a8acdfSMarcus Boerger					if (is_callable_error) {
78322c38b2eSAaron Piotrowski						*severity = E_ERROR;
784a50e9d87SNikita Popov						zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error);
785e8a8acdfSMarcus Boerger						efree(is_callable_error);
786e8a8acdfSMarcus Boerger						return "";
787e8a8acdfSMarcus Boerger					} else {
788e8a8acdfSMarcus Boerger						return "valid callback";
789e8a8acdfSMarcus Boerger					}
79064c353abSMarcus Boerger				}
79164c353abSMarcus Boerger			}
79264c353abSMarcus Boerger
79358f88057SAndrei Zmievski		case 'z':
79458f88057SAndrei Zmievski			{
79558f88057SAndrei Zmievski				zval **p = va_arg(*va, zval **);
79641e3fdbaSAndrea Faulds
79741e3fdbaSAndrea Faulds				zend_parse_arg_zval_deref(real_arg, p, check_null);
798939ab686SAndi Gutmans			}
799939ab686SAndi Gutmans			break;
800b4892511SJani Taskinen
801f4cfaf36SDmitry Stogov		case 'Z':
802f9b26bc3SDmitry Stogov			/* 'Z' iz not supported anymore and should be replaced with 'z' */
8037e03f371SDmitry Stogov			ZEND_ASSERT(c != 'Z');
80458f88057SAndrei Zmievski		default:
80558f88057SAndrei Zmievski			return "unknown";
80658f88057SAndrei Zmievski	}
80758f88057SAndrei Zmievski
80858f88057SAndrei Zmievski	*spec = spec_walk;
80958f88057SAndrei Zmievski
81058f88057SAndrei Zmievski	return NULL;
81158f88057SAndrei Zmievski}
812b4892511SJani Taskinen/* }}} */
81358f88057SAndrei Zmievski
81435f9b90bSDmitry Stogovstatic int zend_parse_arg(int arg_num, zval *arg, va_list *va, const char **spec, int flags) /* {{{ */
81558f88057SAndrei Zmievski{
8164a25a774SDmitry Stogov	const char *expected_type = NULL;
8174a25a774SDmitry Stogov	char *error = NULL;
818e874f760SBob Weinand	int severity = 0;
81958f88057SAndrei Zmievski
82035f9b90bSDmitry Stogov	expected_type = zend_parse_arg_impl(arg_num, arg, va, spec, &error, &severity);
82158f88057SAndrei Zmievski	if (expected_type) {
82235f9b90bSDmitry Stogov		if (!(flags & ZEND_PARSE_PARAMS_QUIET) && (*expected_type || error)) {
8234a25a774SDmitry Stogov			const char *space;
824bdeb220fSAnatol Belski			const char *class_name = get_active_class_name(&space);
825122d7596SNikita Popov			zend_bool throw_exception =
826122d7596SNikita Popov				ZEND_ARG_USES_STRICT_TYPES() || (flags & ZEND_PARSE_PARAMS_THROW);
827baf8cadeSAntony Dovgal
828e8a8acdfSMarcus Boerger			if (error) {
829122d7596SNikita Popov				zend_internal_type_error(throw_exception, "%s%s%s() expects parameter %d %s",
830122d7596SNikita Popov						class_name, space, get_active_function_name(), arg_num, error);
831e8a8acdfSMarcus Boerger				efree(error);
832e8a8acdfSMarcus Boerger			} else {
833122d7596SNikita Popov				zend_internal_type_error(throw_exception,
834122d7596SNikita Popov						"%s%s%s() expects parameter %d to be %s, %s given",
835bdeb220fSAnatol Belski						class_name, space, get_active_function_name(), arg_num, expected_type,
836f4cfaf36SDmitry Stogov						zend_zval_type_name(arg));
837e8a8acdfSMarcus Boerger			}
838e8a8acdfSMarcus Boerger		}
8398d003858SNikita Popov		if (severity != E_DEPRECATED) {
840e8a8acdfSMarcus Boerger			return FAILURE;
84158f88057SAndrei Zmievski		}
84258f88057SAndrei Zmievski	}
843637a4042SMarcus Boerger
84458f88057SAndrei Zmievski	return SUCCESS;
84558f88057SAndrei Zmievski}
846b4892511SJani Taskinen/* }}} */
84758f88057SAndrei Zmievski
848bdeb220fSAnatol BelskiZEND_API int zend_parse_parameter(int flags, int arg_num, zval *arg, const char *spec, ...)
84913f1d53bSGustavo André dos Santos Lopes{
85013f1d53bSGustavo André dos Santos Lopes	va_list va;
85113f1d53bSGustavo André dos Santos Lopes	int ret;
85213f1d53bSGustavo André dos Santos Lopes
85313f1d53bSGustavo André dos Santos Lopes	va_start(va, spec);
85435f9b90bSDmitry Stogov	ret = zend_parse_arg(arg_num, arg, &va, &spec, flags);
85513f1d53bSGustavo André dos Santos Lopes	va_end(va);
85613f1d53bSGustavo André dos Santos Lopes
85713f1d53bSGustavo André dos Santos Lopes	return ret;
85813f1d53bSGustavo André dos Santos Lopes}
85913f1d53bSGustavo André dos Santos Lopes
86071af54e5SDmitry Stogovstatic ZEND_COLD void zend_parse_parameters_debug_error(const char *msg) {
861f920f974SNikita Popov	zend_function *active_function = EG(current_execute_data)->func;
862f920f974SNikita Popov	const char *class_name = active_function->common.scope
8637aa76271SDmitry Stogov		? ZSTR_VAL(active_function->common.scope->name) : "";
864f920f974SNikita Popov	zend_error_noreturn(E_CORE_ERROR, "%s%s%s(): %s",
865f920f974SNikita Popov		class_name, class_name[0] ? "::" : "",
8667aa76271SDmitry Stogov		ZSTR_VAL(active_function->common.function_name), msg);
867f920f974SNikita Popov}
868f920f974SNikita Popov
869bdeb220fSAnatol Belskistatic int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, int flags) /* {{{ */
87058f88057SAndrei Zmievski{
871aaa2f1c3SHartmut Holzgraefe	const  char *spec_walk;
87258f88057SAndrei Zmievski	int c, i;
87358f88057SAndrei Zmievski	int min_num_args = -1;
87458f88057SAndrei Zmievski	int max_num_args = 0;
875b38282c3SSara Golemon	int post_varargs = 0;
876f4cfaf36SDmitry Stogov	zval *arg;
87758f88057SAndrei Zmievski	int arg_count;
878b38282c3SSara Golemon	zend_bool have_varargs = 0;
879a0fe8e5aSDmitry Stogov	zval **varargs = NULL;
880b4892511SJani Taskinen	int *n_varargs = NULL;
88158f88057SAndrei Zmievski
88258f88057SAndrei Zmievski	for (spec_walk = type_spec; *spec_walk; spec_walk++) {
88358f88057SAndrei Zmievski		c = *spec_walk;
88458f88057SAndrei Zmievski		switch (c) {
88558f88057SAndrei Zmievski			case 'l': case 'd':
88658f88057SAndrei Zmievski			case 's': case 'b':
88758f88057SAndrei Zmievski			case 'r': case 'a':
88858f88057SAndrei Zmievski			case 'o': case 'O':
889af1254e4SAndi Gutmans			case 'z': case 'Z':
8902e37e863SMarcus Boerger			case 'C': case 'h':
891fce39ed9SStanislav Malyshev			case 'f': case 'A':
89232b5f8a1SFelipe Pena			case 'H': case 'p':
893bea30846SXinchen Hui			case 'S': case 'P':
894c3e3c98eSAnatol Belski			case 'L':
89558f88057SAndrei Zmievski				max_num_args++;
89658f88057SAndrei Zmievski				break;
89758f88057SAndrei Zmievski
89858f88057SAndrei Zmievski			case '|':
89958f88057SAndrei Zmievski				min_num_args = max_num_args;
90058f88057SAndrei Zmievski				break;
90158f88057SAndrei Zmievski
90258f88057SAndrei Zmievski			case '/':
90358f88057SAndrei Zmievski			case '!':
90458f88057SAndrei Zmievski				/* Pass */
90558f88057SAndrei Zmievski				break;
90658f88057SAndrei Zmievski
907b38282c3SSara Golemon			case '*':
908b38282c3SSara Golemon			case '+':
909b38282c3SSara Golemon				if (have_varargs) {
910f920f974SNikita Popov					zend_parse_parameters_debug_error(
911f920f974SNikita Popov						"only one varargs specifier (* or +) is permitted");
912b38282c3SSara Golemon					return FAILURE;
913b38282c3SSara Golemon				}
914b38282c3SSara Golemon				have_varargs = 1;
915b38282c3SSara Golemon				/* we expect at least one parameter in varargs */
916b38282c3SSara Golemon				if (c == '+') {
917b38282c3SSara Golemon					max_num_args++;
918b38282c3SSara Golemon				}
919b38282c3SSara Golemon				/* mark the beginning of varargs */
920b38282c3SSara Golemon				post_varargs = max_num_args;
921b38282c3SSara Golemon				break;
922b38282c3SSara Golemon
92358f88057SAndrei Zmievski			default:
924f920f974SNikita Popov				zend_parse_parameters_debug_error("bad type specifier while parsing parameters");
92558f88057SAndrei Zmievski				return FAILURE;
92658f88057SAndrei Zmievski		}
92758f88057SAndrei Zmievski	}
92858f88057SAndrei Zmievski
92958f88057SAndrei Zmievski	if (min_num_args < 0) {
93058f88057SAndrei Zmievski		min_num_args = max_num_args;
93158f88057SAndrei Zmievski	}
93258f88057SAndrei Zmievski
933b38282c3SSara Golemon	if (have_varargs) {
934b38282c3SSara Golemon		/* calculate how many required args are at the end of the specifier list */
935b38282c3SSara Golemon		post_varargs = max_num_args - post_varargs;
936b38282c3SSara Golemon		max_num_args = -1;
937b38282c3SSara Golemon	}
938b38282c3SSara Golemon
93995dbe1d0SBob Weinand	if (num_args < min_num_args || (num_args > max_num_args && max_num_args >= 0)) {
94035f9b90bSDmitry Stogov		if (!(flags & ZEND_PARSE_PARAMS_QUIET)) {
941412ad4b2SDmitry Stogov			zend_function *active_function = EG(current_execute_data)->func;
9427aa76271SDmitry Stogov			const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
94395dbe1d0SBob Weinand			zend_bool throw_exception = ZEND_ARG_USES_STRICT_TYPES() || (flags & ZEND_PARSE_PARAMS_THROW);
94412ee17d5SDavey Shafik			zend_internal_argument_count_error(throw_exception, "%s%s%s() expects %s %d parameter%s, %d given",
945e08aedf5SMarcus Boerger					class_name,
946e08aedf5SMarcus Boerger					class_name[0] ? "::" : "",
9477aa76271SDmitry Stogov					ZSTR_VAL(active_function->common.function_name),
94858f88057SAndrei Zmievski					min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
94958f88057SAndrei Zmievski					num_args < min_num_args ? min_num_args : max_num_args,
95058f88057SAndrei Zmievski					(num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
95158f88057SAndrei Zmievski					num_args);
95258f88057SAndrei Zmievski		}
95358f88057SAndrei Zmievski		return FAILURE;
95458f88057SAndrei Zmievski	}
95558f88057SAndrei Zmievski
95611384ba7SDmitry Stogov	arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
95758f88057SAndrei Zmievski
95858f88057SAndrei Zmievski	if (num_args > arg_count) {
959f920f974SNikita Popov		zend_parse_parameters_debug_error("could not obtain parameters for parsing");
96058f88057SAndrei Zmievski		return FAILURE;
96158f88057SAndrei Zmievski	}
96258f88057SAndrei Zmievski
96358f88057SAndrei Zmievski	i = 0;
96458f88057SAndrei Zmievski	while (num_args-- > 0) {
96558f88057SAndrei Zmievski		if (*type_spec == '|') {
96658f88057SAndrei Zmievski			type_spec++;
96758f88057SAndrei Zmievski		}
968b38282c3SSara Golemon
969b38282c3SSara Golemon		if (*type_spec == '*' || *type_spec == '+') {
970b38282c3SSara Golemon			int num_varargs = num_args + 1 - post_varargs;
971b38282c3SSara Golemon
972b38282c3SSara Golemon			/* eat up the passed in storage even if it won't be filled in with varargs */
973a0fe8e5aSDmitry Stogov			varargs = va_arg(*va, zval **);
974b4892511SJani Taskinen			n_varargs = va_arg(*va, int *);
975b38282c3SSara Golemon			type_spec++;
976b38282c3SSara Golemon
977b38282c3SSara Golemon			if (num_varargs > 0) {
978b38282c3SSara Golemon				*n_varargs = num_varargs;
979412ad4b2SDmitry Stogov				*varargs = ZEND_CALL_ARG(EG(current_execute_data), i + 1);
980b38282c3SSara Golemon				/* adjust how many args we have left and restart loop */
981040dea8bSDmitry Stogov				num_args += 1 - num_varargs;
982040dea8bSDmitry Stogov				i += num_varargs;
983b38282c3SSara Golemon				continue;
984b38282c3SSara Golemon			} else {
985b38282c3SSara Golemon				*varargs = NULL;
986b38282c3SSara Golemon				*n_varargs = 0;
987b38282c3SSara Golemon			}
988b38282c3SSara Golemon		}
989b38282c3SSara Golemon
990412ad4b2SDmitry Stogov		arg = ZEND_CALL_ARG(EG(current_execute_data), i + 1);
991b38282c3SSara Golemon
99235f9b90bSDmitry Stogov		if (zend_parse_arg(i+1, arg, va, &type_spec, flags) == FAILURE) {
993b4892511SJani Taskinen			/* clean up varargs array if it was used */
994b4892511SJani Taskinen			if (varargs && *varargs) {