xref: /PHP-8.1/Zend/zend_API.c (revision a8c6c616)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) Zend Technologies Ltd. (http://www.zend.com)           |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 2.00 of the Zend license,     |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.zend.com/license/2_00.txt.                                |
11    | If you did not receive a copy of the Zend license and are unable to  |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@zend.com so we can mail you a copy immediately.              |
14    +----------------------------------------------------------------------+
15    | Authors: Andi Gutmans <andi@php.net>                                 |
16    |          Zeev Suraski <zeev@php.net>                                 |
17    |          Andrei Zmievski <andrei@php.net>                            |
18    |          Dmitry Stogov <dmitry@php.net>                              |
19    +----------------------------------------------------------------------+
20 */
21 
22 #include "zend.h"
23 #include "zend_execute.h"
24 #include "zend_API.h"
25 #include "zend_modules.h"
26 #include "zend_extensions.h"
27 #include "zend_constants.h"
28 #include "zend_interfaces.h"
29 #include "zend_exceptions.h"
30 #include "zend_closures.h"
31 #include "zend_inheritance.h"
32 #include "zend_ini.h"
33 
34 #include <stdarg.h>
35 
36 /* these variables are true statics/globals, and have to be mutex'ed on every access */
37 ZEND_API HashTable module_registry;
38 
39 static zend_module_entry **module_request_startup_handlers;
40 static zend_module_entry **module_request_shutdown_handlers;
41 static zend_module_entry **module_post_deactivate_handlers;
42 
43 static zend_class_entry  **class_cleanup_handlers;
44 
_zend_get_parameters_array_ex(uint32_t param_count,zval * argument_array)45 ZEND_API zend_result _zend_get_parameters_array_ex(uint32_t param_count, zval *argument_array) /* {{{ */
46 {
47 	zval *param_ptr;
48 	uint32_t arg_count;
49 
50 	param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1);
51 	arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
52 
53 	if (param_count>arg_count) {
54 		return FAILURE;
55 	}
56 
57 	while (param_count-->0) {
58 		ZVAL_COPY_VALUE(argument_array, param_ptr);
59 		argument_array++;
60 		param_ptr++;
61 	}
62 
63 	return SUCCESS;
64 }
65 /* }}} */
66 
zend_copy_parameters_array(uint32_t param_count,zval * argument_array)67 ZEND_API zend_result zend_copy_parameters_array(uint32_t param_count, zval *argument_array) /* {{{ */
68 {
69 	zval *param_ptr;
70 	uint32_t arg_count;
71 
72 	param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1);
73 	arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
74 
75 	if (param_count>arg_count) {
76 		return FAILURE;
77 	}
78 
79 	while (param_count-->0) {
80 		Z_TRY_ADDREF_P(param_ptr);
81 		zend_hash_next_index_insert_new(Z_ARRVAL_P(argument_array), param_ptr);
82 		param_ptr++;
83 	}
84 
85 	return SUCCESS;
86 }
87 /* }}} */
88 
zend_wrong_param_count(void)89 ZEND_API ZEND_COLD void zend_wrong_param_count(void) /* {{{ */
90 {
91 	const char *space;
92 	const char *class_name = get_active_class_name(&space);
93 
94 	zend_argument_count_error("Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name());
95 }
96 /* }}} */
97 
98 /* Argument parsing API -- andrei */
zend_get_type_by_const(int type)99 ZEND_API const char *zend_get_type_by_const(int type) /* {{{ */
100 {
101 	switch(type) {
102 		case IS_FALSE:
103 		case IS_TRUE:
104 		case _IS_BOOL:
105 			return "bool";
106 		case IS_LONG:
107 			return "int";
108 		case IS_DOUBLE:
109 			return "float";
110 		case IS_STRING:
111 			return "string";
112 		case IS_OBJECT:
113 			return "object";
114 		case IS_RESOURCE:
115 			return "resource";
116 		case IS_NULL:
117 			return "null";
118 		case IS_CALLABLE:
119 			return "callable";
120 		case IS_ITERABLE:
121 			return "iterable";
122 		case IS_ARRAY:
123 			return "array";
124 		case IS_VOID:
125 			return "void";
126 		case IS_MIXED:
127 			return "mixed";
128 		case _IS_NUMBER:
129 			return "number";
130 		EMPTY_SWITCH_DEFAULT_CASE()
131 	}
132 }
133 /* }}} */
134 
zend_zval_type_name(const zval * arg)135 ZEND_API const char *zend_zval_type_name(const zval *arg) /* {{{ */
136 {
137 	ZVAL_DEREF(arg);
138 
139 	if (Z_ISUNDEF_P(arg)) {
140 		return "null";
141 	}
142 
143 	if (Z_TYPE_P(arg) == IS_OBJECT) {
144 		return ZSTR_VAL(Z_OBJCE_P(arg)->name);
145 	}
146 
147 	return zend_get_type_by_const(Z_TYPE_P(arg));
148 }
149 /* }}} */
150 
151 /* This API exists *only* for use in gettype().
152  * For anything else, you likely want zend_zval_type_name(). */
zend_zval_get_legacy_type(const zval * arg)153 ZEND_API zend_string *zend_zval_get_legacy_type(const zval *arg) /* {{{ */
154 {
155 	switch (Z_TYPE_P(arg)) {
156 		case IS_NULL:
157 			return ZSTR_KNOWN(ZEND_STR_NULL);
158 		case IS_FALSE:
159 		case IS_TRUE:
160 			return ZSTR_KNOWN(ZEND_STR_BOOLEAN);
161 		case IS_LONG:
162 			return ZSTR_KNOWN(ZEND_STR_INTEGER);
163 		case IS_DOUBLE:
164 			return ZSTR_KNOWN(ZEND_STR_DOUBLE);
165 		case IS_STRING:
166 			return ZSTR_KNOWN(ZEND_STR_STRING);
167 		case IS_ARRAY:
168 			return ZSTR_KNOWN(ZEND_STR_ARRAY);
169 		case IS_OBJECT:
170 			return ZSTR_KNOWN(ZEND_STR_OBJECT);
171 		case IS_RESOURCE:
172 			if (zend_rsrc_list_get_rsrc_type(Z_RES_P(arg))) {
173 				return ZSTR_KNOWN(ZEND_STR_RESOURCE);
174 			} else {
175 				return ZSTR_KNOWN(ZEND_STR_CLOSED_RESOURCE);
176 			}
177 		default:
178 			return NULL;
179 	}
180 }
181 /* }}} */
182 
zend_wrong_parameters_none_error(void)183 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_none_error(void) /* {{{ */
184 {
185 	int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
186 	zend_string *func_name = get_active_function_or_method_name();
187 
188 	zend_argument_count_error("%s() expects exactly 0 arguments, %d given", ZSTR_VAL(func_name), num_args);
189 
190 	zend_string_release(func_name);
191 }
192 /* }}} */
193 
zend_wrong_parameters_count_error(uint32_t min_num_args,uint32_t max_num_args)194 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_error(uint32_t min_num_args, uint32_t max_num_args) /* {{{ */
195 {
196 	uint32_t num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
197 	zend_string *func_name = get_active_function_or_method_name();
198 
199 	zend_argument_count_error(
200 		"%s() expects %s %d argument%s, %d given",
201 		ZSTR_VAL(func_name),
202 		min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
203 		num_args < min_num_args ? min_num_args : max_num_args,
204 		(num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
205 		num_args
206 	);
207 
208 	zend_string_release(func_name);
209 }
210 /* }}} */
211 
zend_wrong_parameter_error(int error_code,uint32_t num,char * name,zend_expected_type expected_type,zval * arg)212 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_error(int error_code, uint32_t num, char *name, zend_expected_type expected_type, zval *arg) /* {{{ */
213 {
214 	switch (error_code) {
215 		case ZPP_ERROR_WRONG_CALLBACK:
216 			zend_wrong_callback_error(num, name);
217 			break;
218 		case ZPP_ERROR_WRONG_CALLBACK_OR_NULL:
219 			zend_wrong_callback_or_null_error(num, name);
220 			break;
221 		case ZPP_ERROR_WRONG_CLASS:
222 			zend_wrong_parameter_class_error(num, name, arg);
223 			break;
224 		case ZPP_ERROR_WRONG_CLASS_OR_NULL:
225 			zend_wrong_parameter_class_or_null_error(num, name, arg);
226 			break;
227 		case ZPP_ERROR_WRONG_CLASS_OR_STRING:
228 			zend_wrong_parameter_class_or_string_error(num, name, arg);
229 			break;
230 		case ZPP_ERROR_WRONG_CLASS_OR_STRING_OR_NULL:
231 			zend_wrong_parameter_class_or_string_or_null_error(num, name, arg);
232 			break;
233 		case ZPP_ERROR_WRONG_CLASS_OR_LONG:
234 			zend_wrong_parameter_class_or_long_error(num, name, arg);
235 			break;
236 		case ZPP_ERROR_WRONG_CLASS_OR_LONG_OR_NULL:
237 			zend_wrong_parameter_class_or_long_or_null_error(num, name, arg);
238 			break;
239 		case ZPP_ERROR_WRONG_ARG:
240 			zend_wrong_parameter_type_error(num, expected_type, arg);
241 			break;
242 		case ZPP_ERROR_UNEXPECTED_EXTRA_NAMED:
243 			zend_unexpected_extra_named_error();
244 			break;
245 		case ZPP_ERROR_FAILURE:
246 			ZEND_ASSERT(EG(exception) && "Should have produced an error already");
247 			break;
248 		EMPTY_SWITCH_DEFAULT_CASE()
249 	}
250 }
251 /* }}} */
252 
zend_wrong_parameter_type_error(uint32_t num,zend_expected_type expected_type,zval * arg)253 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(uint32_t num, zend_expected_type expected_type, zval *arg) /* {{{ */
254 {
255 	static const char * const expected_error[] = {
256 		Z_EXPECTED_TYPES(Z_EXPECTED_TYPE_STR)
257 		NULL
258 	};
259 
260 	if (EG(exception)) {
261 		return;
262 	}
263 
264 	if ((expected_type == Z_EXPECTED_PATH || expected_type == Z_EXPECTED_PATH_OR_NULL)
265 			&& Z_TYPE_P(arg) == IS_STRING) {
266 		zend_argument_value_error(num, "must not contain any null bytes");
267 		return;
268 	}
269 
270 	zend_argument_type_error(num, "must be %s, %s given", expected_error[expected_type], zend_zval_type_name(arg));
271 }
272 /* }}} */
273 
zend_wrong_parameter_class_error(uint32_t num,const char * name,zval * arg)274 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(uint32_t num, const char *name, zval *arg) /* {{{ */
275 {
276 	if (EG(exception)) {
277 		return;
278 	}
279 
280 	zend_argument_type_error(num, "must be of type %s, %s given", name, zend_zval_type_name(arg));
281 }
282 /* }}} */
283 
zend_wrong_parameter_class_or_null_error(uint32_t num,const char * name,zval * arg)284 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_null_error(uint32_t num, const char *name, zval *arg) /* {{{ */
285 {
286 	if (EG(exception)) {
287 		return;
288 	}
289 
290 	zend_argument_type_error(num, "must be of type ?%s, %s given", name, zend_zval_type_name(arg));
291 }
292 /* }}} */
293 
zend_wrong_parameter_class_or_long_error(uint32_t num,const char * name,zval * arg)294 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_error(uint32_t num, const char *name, zval *arg) /* {{{ */
295 {
296 	if (EG(exception)) {
297 		return;
298 	}
299 
300 	zend_argument_type_error(num, "must be of type %s|int, %s given", name, zend_zval_type_name(arg));
301 }
302 /* }}} */
303 
zend_wrong_parameter_class_or_long_or_null_error(uint32_t num,const char * name,zval * arg)304 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_or_null_error(uint32_t num, const char *name, zval *arg) /* {{{ */
305 {
306 	if (EG(exception)) {
307 		return;
308 	}
309 
310 	zend_argument_type_error(num, "must be of type %s|int|null, %s given", name, zend_zval_type_name(arg));
311 }
312 /* }}} */
313 
zend_wrong_parameter_class_or_string_error(uint32_t num,const char * name,zval * arg)314 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_error(uint32_t num, const char *name, zval *arg) /* {{{ */
315 {
316 	if (EG(exception)) {
317 		return;
318 	}
319 
320 	zend_argument_type_error(num, "must be of type %s|string, %s given", name, zend_zval_type_name(arg));
321 }
322 /* }}} */
323 
zend_wrong_parameter_class_or_string_or_null_error(uint32_t num,const char * name,zval * arg)324 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_or_null_error(uint32_t num, const char *name, zval *arg) /* {{{ */
325 {
326 	if (EG(exception)) {
327 		return;
328 	}
329 
330 	zend_argument_type_error(num, "must be of type %s|string|null, %s given", name, zend_zval_type_name(arg));
331 }
332 /* }}} */
333 
zend_wrong_callback_error(uint32_t num,char * error)334 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(uint32_t num, char *error) /* {{{ */
335 {
336 	if (!EG(exception)) {
337 		zend_argument_type_error(num, "must be a valid callback, %s", error);
338 	}
339 	efree(error);
340 }
341 /* }}} */
342 
zend_wrong_callback_or_null_error(uint32_t num,char * error)343 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_or_null_error(uint32_t num, char *error) /* {{{ */
344 {
345 	if (!EG(exception)) {
346 		zend_argument_type_error(num, "must be a valid callback or null, %s", error);
347 	}
348 	efree(error);
349 }
350 /* }}} */
351 
zend_unexpected_extra_named_error(void)352 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_unexpected_extra_named_error(void)
353 {
354 	const char *space;
355 	const char *class_name = get_active_class_name(&space);
356 	zend_argument_count_error("%s%s%s() does not accept unknown named parameters",
357 		class_name, space, get_active_function_name());
358 }
359 
zend_argument_error_variadic(zend_class_entry * error_ce,uint32_t arg_num,const char * format,va_list va)360 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) /* {{{ */
361 {
362 	zend_string *func_name;
363 	const char *arg_name;
364 	char *message = NULL;
365 	if (EG(exception)) {
366 		return;
367 	}
368 
369 	func_name = get_active_function_or_method_name();
370 	arg_name = get_active_function_arg_name(arg_num);
371 
372 	zend_vspprintf(&message, 0, format, va);
373 	zend_throw_error(error_ce, "%s(): Argument #%d%s%s%s %s",
374 		ZSTR_VAL(func_name), arg_num,
375 		arg_name ? " ($" : "", arg_name ? arg_name : "", arg_name ? ")" : "", message
376 	);
377 	efree(message);
378 	zend_string_release(func_name);
379 }
380 /* }}} */
381 
zend_argument_error(zend_class_entry * error_ce,uint32_t arg_num,const char * format,...)382 ZEND_API ZEND_COLD void zend_argument_error(zend_class_entry *error_ce, uint32_t arg_num, const char *format, ...) /* {{{ */
383 {
384 	va_list va;
385 
386 	va_start(va, format);
387 	zend_argument_error_variadic(error_ce, arg_num, format, va);
388 	va_end(va);
389 }
390 /* }}} */
391 
zend_argument_type_error(uint32_t arg_num,const char * format,...)392 ZEND_API ZEND_COLD void zend_argument_type_error(uint32_t arg_num, const char *format, ...) /* {{{ */
393 {
394 	va_list va;
395 
396 	va_start(va, format);
397 	zend_argument_error_variadic(zend_ce_type_error, arg_num, format, va);
398 	va_end(va);
399 }
400 /* }}} */
401 
zend_argument_value_error(uint32_t arg_num,const char * format,...)402 ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format, ...) /* {{{ */
403 {
404 	va_list va;
405 
406 	va_start(va, format);
407 	zend_argument_error_variadic(zend_ce_value_error, arg_num, format, va);
408 	va_end(va);
409 }
410 /* }}} */
411 
zend_parse_arg_class(zval * arg,zend_class_entry ** pce,uint32_t num,bool check_null)412 ZEND_API bool ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **pce, uint32_t num, bool check_null) /* {{{ */
413 {
414 	zend_class_entry *ce_base = *pce;
415 
416 	if (check_null && Z_TYPE_P(arg) == IS_NULL) {
417 		*pce = NULL;
418 		return 1;
419 	}
420 	if (!try_convert_to_string(arg)) {
421 		*pce = NULL;
422 		return 0;
423 	}
424 
425 	*pce = zend_lookup_class(Z_STR_P(arg));
426 	if (ce_base) {
427 		if ((!*pce || !instanceof_function(*pce, ce_base))) {
428 			zend_argument_type_error(num, "must be a class name derived from %s, %s given", ZSTR_VAL(ce_base->name), Z_STRVAL_P(arg));
429 			*pce = NULL;
430 			return 0;
431 		}
432 	}
433 	if (!*pce) {
434 		zend_argument_type_error(num, "must be a valid class name, %s given", Z_STRVAL_P(arg));
435 		return 0;
436 	}
437 	return 1;
438 }
439 /* }}} */
440 
zend_null_arg_deprecated(const char * fallback_type,uint32_t arg_num)441 static ZEND_COLD bool zend_null_arg_deprecated(const char *fallback_type, uint32_t arg_num) {
442 	zend_function *func = EG(current_execute_data)->func;
443 	ZEND_ASSERT(arg_num > 0);
444 	uint32_t arg_offset = arg_num - 1;
445 	if (arg_offset >= func->common.num_args) {
446 		ZEND_ASSERT(func->common.fn_flags & ZEND_ACC_VARIADIC);
447 		arg_offset = func->common.num_args;
448 	}
449 
450 	zend_arg_info *arg_info = &func->common.arg_info[arg_offset];
451 	zend_string *func_name = get_active_function_or_method_name();
452 	const char *arg_name = get_active_function_arg_name(arg_num);
453 
454 	/* If no type is specified in arginfo, use the specified fallback_type determined through
455 	 * zend_parse_parameters instead. */
456 	zend_string *type_str = zend_type_to_string(arg_info->type);
457 	const char *type = type_str ? ZSTR_VAL(type_str) : fallback_type;
458 	zend_error(E_DEPRECATED,
459 		"%s(): Passing null to parameter #%" PRIu32 "%s%s%s of type %s is deprecated",
460 		ZSTR_VAL(func_name), arg_num,
461 		arg_name ? " ($" : "", arg_name ? arg_name : "", arg_name ? ")" : "",
462 		type);
463 	zend_string_release(func_name);
464 	if (type_str) {
465 		zend_string_release(type_str);
466 	}
467 	return !EG(exception);
468 }
469 
zend_parse_arg_bool_weak(zval * arg,bool * dest,uint32_t arg_num)470 ZEND_API bool ZEND_FASTCALL zend_parse_arg_bool_weak(zval *arg, bool *dest, uint32_t arg_num) /* {{{ */
471 {
472 	if (EXPECTED(Z_TYPE_P(arg) <= IS_STRING)) {
473 		if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("bool", arg_num)) {
474 			return 0;
475 		}
476 		*dest = zend_is_true(arg);
477 	} else {
478 		return 0;
479 	}
480 	return 1;
481 }
482 /* }}} */
483 
zend_parse_arg_bool_slow(zval * arg,bool * dest,uint32_t arg_num)484 ZEND_API bool ZEND_FASTCALL zend_parse_arg_bool_slow(zval *arg, bool *dest, uint32_t arg_num) /* {{{ */
485 {
486 	if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
487 		return 0;
488 	}
489 	return zend_parse_arg_bool_weak(arg, dest, arg_num);
490 }
491 /* }}} */
492 
zend_parse_arg_long_weak(zval * arg,zend_long * dest,uint32_t arg_num)493 ZEND_API bool ZEND_FASTCALL zend_parse_arg_long_weak(zval *arg, zend_long *dest, uint32_t arg_num) /* {{{ */
494 {
495 	if (EXPECTED(Z_TYPE_P(arg) == IS_DOUBLE)) {
496 		if (UNEXPECTED(zend_isnan(Z_DVAL_P(arg)))) {
497 			return 0;
498 		}
499 		if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(Z_DVAL_P(arg)))) {
500 			return 0;
501 		} else {
502 			zend_long lval = zend_dval_to_lval(Z_DVAL_P(arg));
503 			if (UNEXPECTED(!zend_is_long_compatible(Z_DVAL_P(arg), lval))) {
504 				/* Check arg_num is not (uint32_t)-1, as otherwise its called by
505 				 * zend_verify_weak_scalar_type_hint_no_sideeffect() */
506 				if (arg_num != (uint32_t)-1) {
507 					zend_incompatible_double_to_long_error(Z_DVAL_P(arg));
508 				}
509 				if (UNEXPECTED(EG(exception))) {
510 					return 0;
511 				}
512 			}
513 			*dest = lval;
514 		}
515 	} else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
516 		double d;
517 		zend_uchar type;
518 
519 		if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), dest, &d)) != IS_LONG)) {
520 			if (EXPECTED(type != 0)) {
521 				zend_long lval;
522 				if (UNEXPECTED(zend_isnan(d))) {
523 					return 0;
524 				}
525 				if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(d))) {
526 					return 0;
527 				}
528 
529 				lval = zend_dval_to_lval(d);
530 				/* This only checks for a fractional part as if doesn't fit it already throws a TypeError */
531 				if (UNEXPECTED(!zend_is_long_compatible(d, lval))) {
532 					/* Check arg_num is not (uint32_t)-1, as otherwise its called by
533 					 * zend_verify_weak_scalar_type_hint_no_sideeffect() */
534 					if (arg_num != (uint32_t)-1) {
535 						zend_incompatible_string_to_long_error(Z_STR_P(arg));
536 					}
537 					if (UNEXPECTED(EG(exception))) {
538 						return 0;
539 					}
540 				}
541 				*dest = lval;
542 			} else {
543 				return 0;
544 			}
545 		}
546 		if (UNEXPECTED(EG(exception))) {
547 			return 0;
548 		}
549 	} else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
550 		if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("int", arg_num)) {
551 			return 0;
552 		}
553 		*dest = 0;
554 	} else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
555 		*dest = 1;
556 	} else {
557 		return 0;
558 	}
559 	return 1;
560 }
561 /* }}} */
562 
zend_parse_arg_long_slow(zval * arg,zend_long * dest,uint32_t arg_num)563 ZEND_API bool ZEND_FASTCALL zend_parse_arg_long_slow(zval *arg, zend_long *dest, uint32_t arg_num) /* {{{ */
564 {
565 	if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
566 		return 0;
567 	}
568 	return zend_parse_arg_long_weak(arg, dest, arg_num);
569 }
570 /* }}} */
571 
zend_parse_arg_double_weak(zval * arg,double * dest,uint32_t arg_num)572 ZEND_API bool ZEND_FASTCALL zend_parse_arg_double_weak(zval *arg, double *dest, uint32_t arg_num) /* {{{ */
573 {
574 	if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
575 		*dest = (double)Z_LVAL_P(arg);
576 	} else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
577 		zend_long l;
578 		zend_uchar type;
579 
580 		if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), &l, dest)) != IS_DOUBLE)) {
581 			if (EXPECTED(type != 0)) {
582 				*dest = (double)(l);
583 			} else {
584 				return 0;
585 			}
586 		}
587 		if (UNEXPECTED(EG(exception))) {
588 			return 0;
589 		}
590 	} else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
591 		if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("float", arg_num)) {
592 			return 0;
593 		}
594 		*dest = 0.0;
595 	} else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
596 		*dest = 1.0;
597 	} else {
598 		return 0;
599 	}
600 	return 1;
601 }
602 /* }}} */
603 
zend_parse_arg_double_slow(zval * arg,double * dest,uint32_t arg_num)604 ZEND_API bool ZEND_FASTCALL zend_parse_arg_double_slow(zval *arg, double *dest, uint32_t arg_num) /* {{{ */
605 {
606 	if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
607 		/* SSTH Exception: IS_LONG may be accepted instead as IS_DOUBLE */
608 		*dest = (double)Z_LVAL_P(arg);
609 	} else if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
610 		return 0;
611 	}
612 	return zend_parse_arg_double_weak(arg, dest, arg_num);
613 }
614 /* }}} */
615 
zend_parse_arg_number_slow(zval * arg,zval ** dest,uint32_t arg_num)616 ZEND_API bool ZEND_FASTCALL zend_parse_arg_number_slow(zval *arg, zval **dest, uint32_t arg_num) /* {{{ */
617 {
618 	if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
619 		return 0;
620 	}
621 	if (Z_TYPE_P(arg) == IS_STRING) {
622 		zend_string *str = Z_STR_P(arg);
623 		zend_long lval;
624 		double dval;
625 		zend_uchar type = is_numeric_str_function(str, &lval, &dval);
626 		if (type == IS_LONG) {
627 			ZVAL_LONG(arg, lval);
628 		} else if (type == IS_DOUBLE) {
629 			ZVAL_DOUBLE(arg, dval);
630 		} else {
631 			return 0;
632 		}
633 		zend_string_release(str);
634 	} else if (Z_TYPE_P(arg) < IS_TRUE) {
635 		if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("int|float", arg_num)) {
636 			return 0;
637 		}
638 		ZVAL_LONG(arg, 0);
639 	} else if (Z_TYPE_P(arg) == IS_TRUE) {
640 		ZVAL_LONG(arg, 1);
641 	} else {
642 		return 0;
643 	}
644 	*dest = arg;
645 	return 1;
646 }
647 /* }}} */
648 
zend_parse_arg_str_weak(zval * arg,zend_string ** dest,uint32_t arg_num)649 ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest, uint32_t arg_num) /* {{{ */
650 {
651 	if (EXPECTED(Z_TYPE_P(arg) < IS_STRING)) {
652 		if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("string", arg_num)) {
653 			return 0;
654 		}
655 		convert_to_string(arg);
656 		*dest = Z_STR_P(arg);
657 	} else if (UNEXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
658 		zend_object *zobj = Z_OBJ_P(arg);
659 		zval obj;
660 		if (zobj->handlers->cast_object(zobj, &obj, IS_STRING) == SUCCESS) {
661 			OBJ_RELEASE(zobj);
662 			ZVAL_COPY_VALUE(arg, &obj);
663 			*dest = Z_STR_P(arg);
664 			return 1;
665 		}
666 		return 0;
667 	} else {
668 		return 0;
669 	}
670 	return 1;
671 }
672 /* }}} */
673 
zend_parse_arg_str_slow(zval * arg,zend_string ** dest,uint32_t arg_num)674 ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, zend_string **dest, uint32_t arg_num) /* {{{ */
675 {
676 	if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
677 		return 0;
678 	}
679 	return zend_parse_arg_str_weak(arg, dest, arg_num);
680 }
681 /* }}} */
682 
zend_parse_arg_str_or_long_slow(zval * arg,zend_string ** dest_str,zend_long * dest_long,uint32_t arg_num)683 ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_or_long_slow(zval *arg, zend_string **dest_str, zend_long *dest_long, uint32_t arg_num) /* {{{ */
684 {
685 	if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
686 		return 0;
687 	}
688 	if (zend_parse_arg_long_weak(arg, dest_long, arg_num)) {
689 		*dest_str = NULL;
690 		return 1;
691 	} else if (zend_parse_arg_str_weak(arg, dest_str, arg_num)) {
692 		*dest_long = 0;
693 		return 1;
694 	} else {
695 		return 0;
696 	}
697 }
698 /* }}} */
699 
zend_parse_arg_impl(zval * arg,va_list * va,const char ** spec,char ** error,uint32_t arg_num)700 static const char *zend_parse_arg_impl(zval *arg, va_list *va, const char **spec, char **error, uint32_t arg_num) /* {{{ */
701 {
702 	const char *spec_walk = *spec;
703 	char c = *spec_walk++;
704 	bool check_null = 0;
705 	bool separate = 0;
706 	zval *real_arg = arg;
707 
708 	/* scan through modifiers */
709 	ZVAL_DEREF(arg);
710 	while (1) {
711 		if (*spec_walk == '/') {
712 			SEPARATE_ZVAL_NOREF(arg);
713 			real_arg = arg;
714 			separate = 1;
715 		} else if (*spec_walk == '!') {
716 			check_null = 1;
717 		} else {
718 			break;
719 		}
720 		spec_walk++;
721 	}
722 
723 	switch (c) {
724 		case 'l':
725 			{
726 				zend_long *p = va_arg(*va, zend_long *);
727 				bool *is_null = NULL;
728 
729 				if (check_null) {
730 					is_null = va_arg(*va, bool *);
731 				}
732 
733 				if (!zend_parse_arg_long(arg, p, is_null, check_null, arg_num)) {
734 					return check_null ? "?int" : "int";
735 				}
736 			}
737 			break;
738 
739 		case 'd':
740 			{
741 				double *p = va_arg(*va, double *);
742 				bool *is_null = NULL;
743 
744 				if (check_null) {
745 					is_null = va_arg(*va, bool *);
746 				}
747 
748 				if (!zend_parse_arg_double(arg, p, is_null, check_null, arg_num)) {
749 					return check_null ? "?float" : "float";
750 				}
751 			}
752 			break;
753 
754 		case 'n':
755 			{
756 				zval **p = va_arg(*va, zval **);
757 
758 				if (!zend_parse_arg_number(arg, p, check_null, arg_num)) {
759 					return check_null ? "int|float|null" : "int|float";
760 				}
761 			}
762 			break;
763 
764 		case 's':
765 			{
766 				char **p = va_arg(*va, char **);
767 				size_t *pl = va_arg(*va, size_t *);
768 				if (!zend_parse_arg_string(arg, p, pl, check_null, arg_num)) {
769 					return check_null ? "?string" : "string";
770 				}
771 			}
772 			break;
773 
774 		case 'p':
775 			{
776 				char **p = va_arg(*va, char **);
777 				size_t *pl = va_arg(*va, size_t *);
778 				if (!zend_parse_arg_path(arg, p, pl, check_null, arg_num)) {
779 					if (Z_TYPE_P(arg) == IS_STRING) {
780 						zend_spprintf(error, 0, "must not contain any null bytes");
781 						return "";
782 					} else {
783 						return check_null ? "?string" : "string";
784 					}
785 				}
786 			}
787 			break;
788 
789 		case 'P':
790 			{
791 				zend_string **str = va_arg(*va, zend_string **);
792 				if (!zend_parse_arg_path_str(arg, str, check_null, arg_num)) {
793 					if (Z_TYPE_P(arg) == IS_STRING) {
794 						zend_spprintf(error, 0, "must not contain any null bytes");
795 						return "";
796 					} else {
797 						return check_null ? "?string" : "string";
798 					}
799 				}
800 			}
801 			break;
802 
803 		case 'S':
804 			{
805 				zend_string **str = va_arg(*va, zend_string **);
806 				if (!zend_parse_arg_str(arg, str, check_null, arg_num)) {
807 					return check_null ? "?string" : "string";
808 				}
809 			}
810 			break;
811 
812 		case 'b':
813 			{
814 				bool *p = va_arg(*va, bool *);
815 				bool *is_null = NULL;
816 
817 				if (check_null) {
818 					is_null = va_arg(*va, bool *);
819 				}
820 
821 				if (!zend_parse_arg_bool(arg, p, is_null, check_null, arg_num)) {
822 					return check_null ? "?bool" : "bool";
823 				}
824 			}
825 			break;
826 
827 		case 'r':
828 			{
829 				zval **p = va_arg(*va, zval **);
830 
831 				if (!zend_parse_arg_resource(arg, p, check_null)) {
832 					return check_null ? "resource or null" : "resource";
833 				}
834 			}
835 			break;
836 
837 		case 'A':
838 		case 'a':
839 			{
840 				zval **p = va_arg(*va, zval **);
841 
842 				if (!zend_parse_arg_array(arg, p, check_null, c == 'A')) {
843 					return check_null ? "?array" : "array";
844 				}
845 			}
846 			break;
847 
848 		case 'H':
849 		case 'h':
850 			{
851 				HashTable **p = va_arg(*va, HashTable **);
852 
853 				if (!zend_parse_arg_array_ht(arg, p, check_null, c == 'H', separate)) {
854 					return check_null ? "?array" : "array";
855 				}
856 			}
857 			break;
858 
859 		case 'o':
860 			{
861 				zval **p = va_arg(*va, zval **);
862 
863 				if (!zend_parse_arg_object(arg, p, NULL, check_null)) {
864 					return check_null ? "?object" : "object";
865 				}
866 			}
867 			break;
868 
869 		case 'O':
870 			{
871 				zval **p = va_arg(*va, zval **);
872 				zend_class_entry *ce = va_arg(*va, zend_class_entry *);
873 
874 				if (!zend_parse_arg_object(arg, p, ce, check_null)) {
875 					if (ce) {
876 						if (check_null) {
877 							zend_spprintf(error, 0, "must be of type ?%s, %s given", ZSTR_VAL(ce->name), zend_zval_type_name(arg));
878 							return "";
879 						} else {
880 							return ZSTR_VAL(ce->name);
881 						}
882 					} else {
883 						return check_null ? "?object" : "object";
884 					}
885 				}
886 			}
887 			break;
888 
889 		case 'C':
890 			{
891 				zend_class_entry *lookup, **pce = va_arg(*va, zend_class_entry **);
892 				zend_class_entry *ce_base = *pce;
893 
894 				if (check_null && Z_TYPE_P(arg) == IS_NULL) {
895 					*pce = NULL;
896 					break;
897 				}
898 				if (!try_convert_to_string(arg)) {
899 					*pce = NULL;
900 					return ""; /* try_convert_to_string() throws an exception */
901 				}
902 
903 				if ((lookup = zend_lookup_class(Z_STR_P(arg))) == NULL) {
904 					*pce = NULL;
905 				} else {
906 					*pce = lookup;
907 				}
908 				if (ce_base) {
909 					if ((!*pce || !instanceof_function(*pce, ce_base))) {
910 						zend_spprintf(error, 0, "must be a class name derived from %s%s, %s given",
911 							ZSTR_VAL(ce_base->name), check_null ? " or null" : "", Z_STRVAL_P(arg));
912 						*pce = NULL;
913 						return "";
914 					}
915 				}
916 				if (!*pce) {
917 					zend_spprintf(error, 0, "must be a valid class name%s, %s given",
918 						check_null ? " or null" : "", Z_STRVAL_P(arg));
919 					return "";
920 				}
921 				break;
922 
923 			}
924 			break;
925 
926 		case 'f':
927 			{
928 				zend_fcall_info *fci = va_arg(*va, zend_fcall_info *);
929 				zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *);
930 				char *is_callable_error = NULL;
931 
932 				if (check_null && Z_TYPE_P(arg) == IS_NULL) {
933 					fci->size = 0;
934 					fcc->function_handler = 0;
935 					break;
936 				}
937 
938 				if (zend_fcall_info_init(arg, 0, fci, fcc, NULL, &is_callable_error) == SUCCESS) {
939 					ZEND_ASSERT(!is_callable_error);
940 					/* Release call trampolines: The function may not get called, in which case
941 					 * the trampoline will leak. Force it to be refetched during
942 					 * zend_call_function instead. */
943 					zend_release_fcall_info_cache(fcc);
944 					break;
945 				}
946 
947 				if (is_callable_error) {
948 					zend_spprintf(error, 0, "must be a valid callback%s, %s", check_null ? " or null" : "", is_callable_error);
949 					efree(is_callable_error);
950 					return "";
951 				} else {
952 					return check_null ? "a valid callback or null" : "a valid callback";
953 				}
954 			}
955 
956 		case 'z':
957 			{
958 				zval **p = va_arg(*va, zval **);
959 
960 				zend_parse_arg_zval_deref(real_arg, p, check_null);
961 			}
962 			break;
963 
964 		case 'Z': /* replace with 'z' */
965 		case 'L': /* replace with 'l' */
966 			ZEND_ASSERT(0 && "ZPP modifier no longer supported");
967 			ZEND_FALLTHROUGH;
968 		default:
969 			return "unknown";
970 	}
971 
972 	*spec = spec_walk;
973 
974 	return NULL;
975 }
976 /* }}} */
977 
zend_parse_arg(uint32_t arg_num,zval * arg,va_list * va,const char ** spec,int flags)978 static zend_result zend_parse_arg(uint32_t arg_num, zval *arg, va_list *va, const char **spec, int flags) /* {{{ */
979 {
980 	const char *expected_type = NULL;
981 	char *error = NULL;
982 
983 	expected_type = zend_parse_arg_impl(arg, va, spec, &error, arg_num);
984 	if (expected_type) {
985 		if (EG(exception)) {
986 			return FAILURE;
987 		}
988 		if (!(flags & ZEND_PARSE_PARAMS_QUIET) && (*expected_type || error)) {
989 			if (error) {
990 				if (strcmp(error, "must not contain any null bytes") == 0) {
991 					zend_argument_value_error(arg_num, "%s", error);
992 				} else {
993 					zend_argument_type_error(arg_num, "%s", error);
994 				}
995 				efree(error);
996 			} else {
997 				zend_argument_type_error(arg_num, "must be of type %s, %s given", expected_type, zend_zval_type_name(arg));
998 			}
999 		} else if (error) {
1000 			efree(error);
1001 		}
1002 
1003 		return FAILURE;
1004 	}
1005 
1006 	return SUCCESS;
1007 }
1008 /* }}} */
1009 
zend_parse_parameter(int flags,uint32_t arg_num,zval * arg,const char * spec,...)1010 ZEND_API zend_result zend_parse_parameter(int flags, uint32_t arg_num, zval *arg, const char *spec, ...)
1011 {
1012 	va_list va;
1013 	zend_result ret;
1014 
1015 	va_start(va, spec);
1016 	ret = zend_parse_arg(arg_num, arg, &va, &spec, flags);
1017 	va_end(va);
1018 
1019 	return ret;
1020 }
1021 
zend_parse_parameters_debug_error(const char * msg)1022 static ZEND_COLD void zend_parse_parameters_debug_error(const char *msg) {
1023 	zend_function *active_function = EG(current_execute_data)->func;
1024 	const char *class_name = active_function->common.scope
1025 		? ZSTR_VAL(active_function->common.scope->name) : "";
1026 	zend_error_noreturn(E_CORE_ERROR, "%s%s%s(): %s",
1027 		class_name, class_name[0] ? "::" : "",
1028 		ZSTR_VAL(active_function->common.function_name), msg);
1029 }
1030 
zend_parse_va_args(uint32_t num_args,const char * type_spec,va_list * va,int flags)1031 static zend_result zend_parse_va_args(uint32_t num_args, const char *type_spec, va_list *va, int flags) /* {{{ */
1032 {
1033 	const  char *spec_walk;
1034 	char c;
1035 	uint32_t i;
1036 	uint32_t min_num_args = 0;
1037 	uint32_t max_num_args = 0;
1038 	uint32_t post_varargs = 0;
1039 	zval *arg;
1040 	bool have_varargs = 0;
1041 	bool have_optional_args = 0;
1042 	zval **varargs = NULL;
1043 	uint32_t *n_varargs = NULL;
1044 
1045 	for (spec_walk = type_spec; *spec_walk; spec_walk++) {
1046 		c = *spec_walk;
1047 		switch (c) {
1048 			case 'l': case 'd':
1049 			case 's': case 'b':
1050 			case 'r': case 'a':
1051 			case 'o': case 'O':
1052 			case 'z': case 'Z':
1053 			case 'C': case 'h':
1054 			case 'f': case 'A':
1055 			case 'H': case 'p':
1056 			case 'S': case 'P':
1057 			case 'L': case 'n':
1058 				max_num_args++;
1059 				break;
1060 
1061 			case '|':
1062 				min_num_args = max_num_args;
1063 				have_optional_args = 1;
1064 				break;
1065 
1066 			case '/':
1067 			case '!':
1068 				/* Pass */
1069 				break;
1070 
1071 			case '*':
1072 			case '+':
1073 				if (have_varargs) {
1074 					zend_parse_parameters_debug_error(
1075 						"only one varargs specifier (* or +) is permitted");
1076 					return FAILURE;
1077 				}
1078 				have_varargs = 1;
1079 				/* we expect at least one parameter in varargs */
1080 				if (c == '+') {
1081 					max_num_args++;
1082 				}
1083 				/* mark the beginning of varargs */
1084 				post_varargs = max_num_args;
1085 
1086 				if (ZEND_CALL_INFO(EG(current_execute_data)) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
1087 					zend_unexpected_extra_named_error();
1088 					return FAILURE;
1089 				}
1090 				break;
1091 
1092 			default:
1093 				zend_parse_parameters_debug_error("bad type specifier while parsing parameters");
1094 				return FAILURE;
1095 		}
1096 	}
1097 
1098 	/* with no optional arguments the minimum number of arguments must be the same as the maximum */
1099 	if (!have_optional_args) {
1100 		min_num_args = max_num_args;
1101 	}
1102 
1103 	if (have_varargs) {
1104 		/* calculate how many required args are at the end of the specifier list */
1105 		post_varargs = max_num_args - post_varargs;
1106 		max_num_args = UINT32_MAX;
1107 	}
1108 
1109 	if (num_args < min_num_args || num_args > max_num_args) {
1110 		if (!(flags & ZEND_PARSE_PARAMS_QUIET)) {
1111 			zend_string *func_name = get_active_function_or_method_name();
1112 
1113 			zend_argument_count_error("%s() expects %s %d argument%s, %d given",
1114 				ZSTR_VAL(func_name),
1115 				min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
1116 				num_args < min_num_args ? min_num_args : max_num_args,
1117 				(num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
1118 				num_args
1119 			);
1120 
1121 			zend_string_release(func_name);
1122 		}
1123 		return FAILURE;
1124 	}
1125 
1126 	if (num_args > ZEND_CALL_NUM_ARGS(EG(current_execute_data))) {
1127 		zend_parse_parameters_debug_error("could not obtain parameters for parsing");
1128 		return FAILURE;
1129 	}
1130 
1131 	i = 0;
1132 	while (num_args-- > 0) {
1133 		if (*type_spec == '|') {
1134 			type_spec++;
1135 		}
1136 
1137 		if (*type_spec == '*' || *type_spec == '+') {
1138 			uint32_t num_varargs = num_args + 1 - post_varargs;
1139 
1140 			/* eat up the passed in storage even if it won't be filled in with varargs */
1141 			varargs = va_arg(*va, zval **);
1142 			n_varargs = va_arg(*va, uint32_t *);
1143 			type_spec++;
1144 
1145 			if (num_varargs > 0) {
1146 				*n_varargs = num_varargs;
1147 				*varargs = ZEND_CALL_ARG(EG(current_execute_data), i + 1);
1148 				/* adjust how many args we have left and restart loop */
1149 				num_args += 1 - num_varargs;
1150 				i += num_varargs;
1151 				continue;
1152 			} else {
1153 				*varargs = NULL;
1154 				*n_varargs = 0;
1155 			}
1156 		}
1157 
1158 		arg = ZEND_CALL_ARG(EG(current_execute_data), i + 1);
1159 
1160 		if (zend_parse_arg(i+1, arg, va, &type_spec, flags) == FAILURE) {
1161 			/* clean up varargs array if it was used */
1162 			if (varargs && *varargs) {
1163 				*varargs = NULL;
1164 			}
1165 			return FAILURE;
1166 		}
1167 		i++;
1168 	}
1169 
1170 	return SUCCESS;
1171 }
1172 /* }}} */
1173 
zend_parse_parameters_ex(int flags,uint32_t num_args,const char * type_spec,...)1174 ZEND_API zend_result zend_parse_parameters_ex(int flags, uint32_t num_args, const char *type_spec, ...) /* {{{ */
1175 {
1176 	va_list va;
1177 	zend_result retval;
1178 
1179 	va_start(va, type_spec);
1180 	retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1181 	va_end(va);
1182 
1183 	return retval;
1184 }
1185 /* }}} */
1186 
zend_parse_parameters(uint32_t num_args,const char * type_spec,...)1187 ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec, ...) /* {{{ */
1188 {
1189 	va_list va;
1190 	zend_result retval;
1191 	int flags = 0;
1192 
1193 	va_start(va, type_spec);
1194 	retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1195 	va_end(va);
1196 
1197 	return retval;
1198 }
1199 /* }}} */
1200 
zend_parse_method_parameters(uint32_t num_args,zval * this_ptr,const char * type_spec,...)1201 ZEND_API zend_result zend_parse_method_parameters(uint32_t num_args, zval *this_ptr, const char *type_spec, ...) /* {{{ */
1202 {
1203 	va_list va;
1204 	zend_result retval;
1205 	int flags = 0;
1206 	const char *p = type_spec;
1207 	zval **object;
1208 	zend_class_entry *ce;
1209 
1210 	/* Just checking this_ptr is not enough, because fcall_common_helper does not set
1211 	 * Z_OBJ(EG(This)) to NULL when calling an internal function with common.scope == NULL.
1212 	 * In that case EG(This) would still be the $this from the calling code and we'd take the
1213 	 * wrong branch here. */
1214 	bool is_method = EG(current_execute_data)->func->common.scope != NULL;
1215 
1216 	if (!is_method || !this_ptr || Z_TYPE_P(this_ptr) != IS_OBJECT) {
1217 		va_start(va, type_spec);
1218 		retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1219 		va_end(va);
1220 	} else {
1221 		p++;
1222 
1223 		va_start(va, type_spec);
1224 
1225 		object = va_arg(va, zval **);
1226 		ce = va_arg(va, zend_class_entry *);
1227 		*object = this_ptr;
1228 
1229 		if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce)) {
1230 			zend_error_noreturn(E_CORE_ERROR, "%s::%s() must be derived from %s::%s()",
1231 				ZSTR_VAL(Z_OBJCE_P(this_ptr)->name), get_active_function_name(), ZSTR_VAL(ce->name), get_active_function_name());
1232 		}
1233 
1234 		retval = zend_parse_va_args(num_args, p, &va, flags);
1235 		va_end(va);
1236 	}
1237 	return retval;
1238 }
1239 /* }}} */
1240 
zend_parse_method_parameters_ex(int flags,uint32_t num_args,zval * this_ptr,const char * type_spec,...)1241 ZEND_API zend_result zend_parse_method_parameters_ex(int flags, uint32_t num_args, zval *this_ptr, const char *type_spec, ...) /* {{{ */
1242 {
1243 	va_list va;
1244 	zend_result retval;
1245 	const char *p = type_spec;
1246 	zval **object;
1247 	zend_class_entry *ce;
1248 
1249 	if (!this_ptr) {
1250 		va_start(va, type_spec);
1251 		retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1252 		va_end(va);
1253 	} else {
1254 		p++;
1255 		va_start(va, type_spec);
1256 
1257 		object = va_arg(va, zval **);
1258 		ce = va_arg(va, zend_class_entry *);
1259 		*object = this_ptr;
1260 
1261 		if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce)) {
1262 			if (!(flags & ZEND_PARSE_PARAMS_QUIET)) {
1263 				zend_error_noreturn(E_CORE_ERROR, "%s::%s() must be derived from %s::%s()",
1264 					ZSTR_VAL(ce->name), get_active_function_name(), ZSTR_VAL(Z_OBJCE_P(this_ptr)->name), get_active_function_name());
1265 			}
1266 			va_end(va);
1267 			return FAILURE;
1268 		}
1269 
1270 		retval = zend_parse_va_args(num_args, p, &va, flags);
1271 		va_end(va);
1272 	}
1273 	return retval;
1274 }
1275 /* }}} */
1276 
1277 /* This function should be called after the constructor has been called
1278  * because it may call __set from the uninitialized object otherwise. */
zend_merge_properties(zval * obj,HashTable * properties)1279 ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */
1280 {
1281 	zend_object *zobj = Z_OBJ_P(obj);
1282 	zend_object_write_property_t write_property = zobj->handlers->write_property;
1283 	zend_class_entry *old_scope = EG(fake_scope);
1284 	zend_string *key;
1285 	zval *value;
1286 
1287 	EG(fake_scope) = Z_OBJCE_P(obj);
1288 	ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, value) {
1289 		if (key) {
1290 			write_property(zobj, key, value, NULL);
1291 		}
1292 	} ZEND_HASH_FOREACH_END();
1293 	EG(fake_scope) = old_scope;
1294 }
1295 /* }}} */
1296 
zend_allocate_mutable_data(zend_class_entry * class_type)1297 static zend_class_mutable_data *zend_allocate_mutable_data(zend_class_entry *class_type) /* {{{ */
1298 {
1299 	zend_class_mutable_data *mutable_data;
1300 
1301 	ZEND_ASSERT(ZEND_MAP_PTR(class_type->mutable_data) != NULL);
1302 	ZEND_ASSERT(ZEND_MAP_PTR_GET_IMM(class_type->mutable_data) == NULL);
1303 
1304 	mutable_data = zend_arena_alloc(&CG(arena), sizeof(zend_class_mutable_data));
1305 	memset(mutable_data, 0, sizeof(zend_class_mutable_data));
1306 	mutable_data->ce_flags = class_type->ce_flags;
1307 	ZEND_MAP_PTR_SET_IMM(class_type->mutable_data, mutable_data);
1308 
1309 	return mutable_data;
1310 }
1311 /* }}} */
1312 
zend_separate_class_constants_table(zend_class_entry * class_type)1313 ZEND_API HashTable *zend_separate_class_constants_table(zend_class_entry *class_type) /* {{{ */
1314 {
1315 	zend_class_mutable_data *mutable_data;
1316 	HashTable *constants_table;
1317 	zend_string *key;
1318 	zend_class_constant *new_c, *c;
1319 
1320 	constants_table = zend_arena_alloc(&CG(arena), sizeof(HashTable));
1321 	zend_hash_init(constants_table, zend_hash_num_elements(&class_type->constants_table), NULL, NULL, 0);
1322 	zend_hash_extend(constants_table, zend_hash_num_elements(&class_type->constants_table), 0);
1323 
1324 	ZEND_HASH_FOREACH_STR_KEY_PTR(&class_type->constants_table, key, c) {
1325 		if (c->ce == class_type) {
1326 			if (Z_TYPE(c->value) == IS_CONSTANT_AST) {
1327 				new_c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
1328 				memcpy(new_c, c, sizeof(zend_class_constant));
1329 				c = new_c;
1330 			}
1331 			Z_TRY_ADDREF(c->value);
1332 		} else {
1333 			if (Z_TYPE(c->value) == IS_CONSTANT_AST) {
1334 				c = zend_hash_find_ptr(CE_CONSTANTS_TABLE(c->ce), key);
1335 				ZEND_ASSERT(c);
1336 			}
1337 		}
1338 		_zend_hash_append_ptr(constants_table, key, c);
1339 	} ZEND_HASH_FOREACH_END();
1340 
1341 	ZEND_ASSERT(ZEND_MAP_PTR(class_type->mutable_data) != NULL);
1342 
1343 	mutable_data = ZEND_MAP_PTR_GET_IMM(class_type->mutable_data);
1344 	if (!mutable_data) {
1345 		mutable_data = zend_allocate_mutable_data(class_type);
1346 	}
1347 
1348 	mutable_data->constants_table = constants_table;
1349 
1350 	return constants_table;
1351 }
1352 
update_property(zval * val,zend_property_info * prop_info)1353 static zend_result update_property(zval *val, zend_property_info *prop_info) {
1354 	if (ZEND_TYPE_IS_SET(prop_info->type)) {
1355 		zval tmp;
1356 
1357 		ZVAL_COPY(&tmp, val);
1358 		if (UNEXPECTED(zval_update_constant_ex(&tmp, prop_info->ce) != SUCCESS)) {
1359 			zval_ptr_dtor(&tmp);
1360 			return FAILURE;
1361 		}
1362 		/* property initializers must always be evaluated with strict types */;
1363 		if (UNEXPECTED(!zend_verify_property_type(prop_info, &tmp, /* strict */ 1))) {
1364 			zval_ptr_dtor(&tmp);
1365 			return FAILURE;
1366 		}
1367 		zval_ptr_dtor(val);
1368 		ZVAL_COPY_VALUE(val, &tmp);
1369 		return SUCCESS;
1370 	}
1371 	return zval_update_constant_ex(val, prop_info->ce);
1372 }
1373 
zend_update_class_constants(zend_class_entry * class_type)1374 ZEND_API zend_result zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
1375 {
1376 	zend_class_mutable_data *mutable_data = NULL;
1377 	zval *default_properties_table = NULL;
1378 	zval *static_members_table = NULL;
1379 	zend_class_constant *c;
1380 	zval *val;
1381 	uint32_t ce_flags;
1382 
1383 	ce_flags = class_type->ce_flags;
1384 
1385 	if (ce_flags & ZEND_ACC_CONSTANTS_UPDATED) {
1386 		return SUCCESS;
1387 	}
1388 
1389 	bool uses_mutable_data = ZEND_MAP_PTR(class_type->mutable_data) != NULL;
1390 	if (uses_mutable_data) {
1391 		mutable_data = ZEND_MAP_PTR_GET_IMM(class_type->mutable_data);
1392 		if (mutable_data) {
1393 			ce_flags = mutable_data->ce_flags;
1394 			if (ce_flags & ZEND_ACC_CONSTANTS_UPDATED) {
1395 				return SUCCESS;
1396 			}
1397 		} else {
1398 			mutable_data = zend_allocate_mutable_data(class_type);
1399 		}
1400 	}
1401 
1402 	if (class_type->parent) {
1403 		if (UNEXPECTED(zend_update_class_constants(class_type->parent) != SUCCESS)) {
1404 			return FAILURE;
1405 		}
1406 	}
1407 
1408 	if (ce_flags & ZEND_ACC_HAS_AST_CONSTANTS) {
1409 		HashTable *constants_table;
1410 
1411 		if (uses_mutable_data) {
1412 			constants_table = mutable_data->constants_table;
1413 			if (!constants_table) {
1414 				constants_table = zend_separate_class_constants_table(class_type);
1415 			}
1416 		} else {
1417 			constants_table = &class_type->constants_table;
1418 		}
1419 
1420 		zend_string *name;
1421 		ZEND_HASH_FOREACH_STR_KEY_VAL(constants_table, name, val) {
1422 			c = Z_PTR_P(val);
1423 			if (Z_TYPE(c->value) == IS_CONSTANT_AST) {
1424 				if (c->ce != class_type) {
1425 					Z_PTR_P(val) = c = zend_hash_find_ptr(CE_CONSTANTS_TABLE(c->ce), name);
1426 					if (Z_TYPE(c->value) != IS_CONSTANT_AST) {
1427 						continue;
1428 					}
1429 				}
1430 
1431 				val = &c->value;
1432 				if (UNEXPECTED(zval_update_constant_ex(val, c->ce) != SUCCESS)) {
1433 					return FAILURE;
1434 				}
1435 			}
1436 		} ZEND_HASH_FOREACH_END();
1437 	}
1438 
1439 	if (class_type->default_static_members_count) {
1440 		static_members_table = CE_STATIC_MEMBERS(class_type);
1441 		if (!static_members_table) {
1442 			zend_class_init_statics(class_type);
1443 			static_members_table = CE_STATIC_MEMBERS(class_type);
1444 		}
1445 	}
1446 
1447 	default_properties_table = class_type->default_properties_table;
1448 	if (uses_mutable_data && (ce_flags & ZEND_ACC_HAS_AST_PROPERTIES)) {
1449 		zval *src, *dst, *end;
1450 
1451 		default_properties_table = mutable_data->default_properties_table;
1452 		if (!default_properties_table) {
1453 			default_properties_table = zend_arena_alloc(&CG(arena), sizeof(zval) * class_type->default_properties_count);
1454 			src = class_type->default_properties_table;
1455 			dst = default_properties_table;
1456 			end = dst + class_type->default_properties_count;
1457 			do {
1458 				ZVAL_COPY_PROP(dst, src);
1459 				src++;
1460 				dst++;
1461 			} while (dst != end);
1462 			mutable_data->default_properties_table = default_properties_table;
1463 		}
1464 	}
1465 
1466 	if (ce_flags & (ZEND_ACC_HAS_AST_PROPERTIES|ZEND_ACC_HAS_AST_STATICS)) {
1467 		zend_property_info *prop_info;
1468 
1469 		/* Use the default properties table to also update initializers of private properties
1470 		 * that have been shadowed in a child class. */
1471 		for (uint32_t i = 0; i < class_type->default_properties_count; i++) {
1472 			val = &default_properties_table[i];
1473 			prop_info = class_type->properties_info_table[i];
1474 			if (Z_TYPE_P(val) == IS_CONSTANT_AST
1475 					&& UNEXPECTED(update_property(val, prop_info) != SUCCESS)) {
1476 				return FAILURE;
1477 			}
1478 		}
1479 
1480 		if (class_type->default_static_members_count) {
1481 			ZEND_HASH_FOREACH_PTR(&class_type->properties_info, prop_info) {
1482 				if (prop_info->flags & ZEND_ACC_STATIC) {
1483 					val = static_members_table + prop_info->offset;
1484 					if (Z_TYPE_P(val) == IS_CONSTANT_AST
1485 							&& UNEXPECTED(update_property(val, prop_info) != SUCCESS)) {
1486 						return FAILURE;
1487 					}
1488 				}
1489 			} ZEND_HASH_FOREACH_END();
1490 		}
1491 	}
1492 
1493 	ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
1494 	ce_flags &= ~ZEND_ACC_HAS_AST_CONSTANTS;
1495 	ce_flags &= ~ZEND_ACC_HAS_AST_PROPERTIES;
1496 	ce_flags &= ~ZEND_ACC_HAS_AST_STATICS;
1497 	if (uses_mutable_data) {
1498 		mutable_data->ce_flags = ce_flags;
1499 	} else {
1500 		class_type->ce_flags = ce_flags;
1501 	}
1502 
1503 	return SUCCESS;
1504 }
1505 /* }}} */
1506 
_object_properties_init(zend_object * object,zend_class_entry * class_type)1507 static zend_always_inline void _object_properties_init(zend_object *object, zend_class_entry *class_type) /* {{{ */
1508 {
1509 	if (class_type->default_properties_count) {
1510 		zval *src = CE_DEFAULT_PROPERTIES_TABLE(class_type);
1511 		zval *dst = object->properties_table;
1512 		zval *end = src + class_type->default_properties_count;
1513 
1514 		if (UNEXPECTED(class_type->type == ZEND_INTERNAL_CLASS)) {
1515 			do {
1516 				ZVAL_COPY_OR_DUP_PROP(dst, src);
1517 				src++;
1518 				dst++;
1519 			} while (src != end);
1520 		} else {
1521 			do {
1522 				ZVAL_COPY_PROP(dst, src);
1523 				src++;
1524 				dst++;
1525 			} while (src != end);
1526 		}
1527 	}
1528 }
1529 /* }}} */
1530 
object_properties_init(zend_object * object,zend_class_entry * class_type)1531 ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type) /* {{{ */
1532 {
1533 	object->properties = NULL;
1534 	_object_properties_init(object, class_type);
1535 }
1536 /* }}} */
1537 
object_properties_init_ex(zend_object * object,HashTable * properties)1538 ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properties) /* {{{ */
1539 {
1540 	object->properties = properties;
1541 	if (object->ce->default_properties_count) {
1542 		zval *prop;
1543 		zend_string *key;
1544 		zend_property_info *property_info;
1545 
1546 		ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) {
1547 			property_info = zend_get_property_info(object->ce, key, 1);
1548 			if (property_info != ZEND_WRONG_PROPERTY_INFO &&
1549 			    property_info &&
1550 			    (property_info->flags & ZEND_ACC_STATIC) == 0) {
1551 				zval *slot = OBJ_PROP(object, property_info->offset);
1552 
1553 				if (UNEXPECTED(ZEND_TYPE_IS_SET(property_info->type))) {
1554 					zval tmp;
1555 
1556 					ZVAL_COPY_VALUE(&tmp, prop);
1557 					if (UNEXPECTED(!zend_verify_property_type(property_info, &tmp, 0))) {
1558 						continue;
1559 					}
1560 					ZVAL_COPY_VALUE(slot, &tmp);
1561 				} else {
1562 					ZVAL_COPY_VALUE(slot, prop);
1563 				}
1564 				ZVAL_INDIRECT(prop, slot);
1565 			}
1566 		} ZEND_HASH_FOREACH_END();
1567 	}
1568 }
1569 /* }}} */
1570 
object_properties_load(zend_object * object,HashTable * properties)1571 ZEND_API void object_properties_load(zend_object *object, HashTable *properties) /* {{{ */
1572 {
1573 	zval *prop, tmp;
1574 	zend_string *key;
1575 	zend_long h;
1576 	zend_property_info *property_info;
1577 
1578 	ZEND_HASH_FOREACH_KEY_VAL(properties, h, key, prop) {
1579 		if (key) {
1580 			if (ZSTR_VAL(key)[0] == '\0') {
1581 				const char *class_name, *prop_name;
1582 				size_t prop_name_len;
1583 				if (zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_name_len) == SUCCESS) {
1584 					zend_string *pname = zend_string_init(prop_name, prop_name_len, 0);
1585 					zend_class_entry *prev_scope = EG(fake_scope);
1586 					if (class_name && class_name[0] != '*') {
1587 						zend_string *cname = zend_string_init(class_name, strlen(class_name), 0);
1588 						EG(fake_scope) = zend_lookup_class(cname);
1589 						zend_string_release_ex(cname, 0);
1590 					}
1591 					property_info = zend_get_property_info(object->ce, pname, 1);
1592 					zend_string_release_ex(pname, 0);
1593 					EG(fake_scope) = prev_scope;
1594 				} else {
1595 					property_info = ZEND_WRONG_PROPERTY_INFO;
1596 				}
1597 			} else {
1598 				property_info = zend_get_property_info(object->ce, key, 1);
1599 			}
1600 			if (property_info != ZEND_WRONG_PROPERTY_INFO &&
1601 				property_info &&
1602 				(property_info->flags & ZEND_ACC_STATIC) == 0) {
1603 				zval *slot = OBJ_PROP(object, property_info->offset);
1604 				zval_ptr_dtor(slot);
1605 				ZVAL_COPY_VALUE(slot, prop);
1606 				zval_add_ref(slot);
1607 				if (object->properties) {
1608 					ZVAL_INDIRECT(&tmp, slot);
1609 					zend_hash_update(object->properties, key, &tmp);
1610 				}
1611 			} else {
1612 				if (!object->properties) {
1613 					rebuild_object_properties(object);
1614 				}
1615 				prop = zend_hash_update(object->properties, key, prop);
1616 				zval_add_ref(prop);
1617 			}
1618 		} else {
1619 			if (!object->properties) {
1620 				rebuild_object_properties(object);
1621 			}
1622 			prop = zend_hash_index_update(object->properties, h, prop);
1623 			zval_add_ref(prop);
1624 		}
1625 	} ZEND_HASH_FOREACH_END();
1626 }
1627 /* }}} */
1628 
1629 /* This function requires 'properties' to contain all props declared in the
1630  * class and all props being public. If only a subset is given or the class
1631  * has protected members then you need to merge the properties separately by
1632  * calling zend_merge_properties(). */
_object_and_properties_init(zval * arg,zend_class_entry * class_type,HashTable * properties)1633 static zend_always_inline zend_result _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties) /* {{{ */
1634 {
1635 	if (UNEXPECTED(class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS|ZEND_ACC_ENUM))) {
1636 		if (class_type->ce_flags & ZEND_ACC_INTERFACE) {
1637 			zend_throw_error(NULL, "Cannot instantiate interface %s", ZSTR_VAL(class_type->name));
1638 		} else if (class_type->ce_flags & ZEND_ACC_TRAIT) {
1639 			zend_throw_error(NULL, "Cannot instantiate trait %s", ZSTR_VAL(class_type->name));
1640 		} else if (class_type->ce_flags & ZEND_ACC_ENUM) {
1641 			zend_throw_error(NULL, "Cannot instantiate enum %s", ZSTR_VAL(class_type->name));
1642 		} else {
1643 			zend_throw_error(NULL, "Cannot instantiate abstract class %s", ZSTR_VAL(class_type->name));
1644 		}
1645 		ZVAL_NULL(arg);
1646 		Z_OBJ_P(arg) = NULL;
1647 		return FAILURE;
1648 	}
1649 
1650 	if (UNEXPECTED(!(class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
1651 		if (UNEXPECTED(zend_update_class_constants(class_type) != SUCCESS)) {
1652 			ZVAL_NULL(arg);
1653 			Z_OBJ_P(arg) = NULL;
1654 			return FAILURE;
1655 		}
1656 	}
1657 
1658 	if (class_type->create_object == NULL) {
1659 		zend_object *obj = zend_objects_new(class_type);
1660 
1661 		ZVAL_OBJ(arg, obj);
1662 		if (properties) {
1663 			object_properties_init_ex(obj, properties);
1664 		} else {
1665 			_object_properties_init(obj, class_type);
1666 		}
1667 	} else {
1668 		ZVAL_OBJ(arg, class_type->create_object(class_type));
1669 	}
1670 	return SUCCESS;
1671 }
1672 /* }}} */
1673 
object_and_properties_init(zval * arg,zend_class_entry * class_type,HashTable * properties)1674 ZEND_API zend_result object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties) /* {{{ */
1675 {
1676 	return _object_and_properties_init(arg, class_type, properties);
1677 }
1678 /* }}} */
1679 
object_init_ex(zval * arg,zend_class_entry * class_type)1680 ZEND_API zend_result object_init_ex(zval *arg, zend_class_entry *class_type) /* {{{ */
1681 {
1682 	return _object_and_properties_init(arg, class_type, NULL);
1683 }
1684 /* }}} */
1685 
object_init(zval * arg)1686 ZEND_API void object_init(zval *arg) /* {{{ */
1687 {
1688 	ZVAL_OBJ(arg, zend_objects_new(zend_standard_class_def));
1689 }
1690 /* }}} */
1691 
add_assoc_long_ex(zval * arg,const char * key,size_t key_len,zend_long n)1692 ZEND_API void add_assoc_long_ex(zval *arg, const char *key, size_t key_len, zend_long n) /* {{{ */
1693 {
1694 	zval tmp;
1695 
1696 	ZVAL_LONG(&tmp, n);
1697 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1698 }
1699 /* }}} */
1700 
add_assoc_null_ex(zval * arg,const char * key,size_t key_len)1701 ZEND_API void add_assoc_null_ex(zval *arg, const char *key, size_t key_len) /* {{{ */
1702 {
1703 	zval tmp;
1704 
1705 	ZVAL_NULL(&tmp);
1706 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1707 }
1708 /* }}} */
1709 
add_assoc_bool_ex(zval * arg,const char * key,size_t key_len,bool b)1710 ZEND_API void add_assoc_bool_ex(zval *arg, const char *key, size_t key_len, bool b) /* {{{ */
1711 {
1712 	zval tmp;
1713 
1714 	ZVAL_BOOL(&tmp, b);
1715 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1716 }
1717 /* }}} */
1718 
add_assoc_resource_ex(zval * arg,const char * key,size_t key_len,zend_resource * r)1719 ZEND_API void add_assoc_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r) /* {{{ */
1720 {
1721 	zval tmp;
1722 
1723 	ZVAL_RES(&tmp, r);
1724 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1725 }
1726 /* }}} */
1727 
add_assoc_double_ex(zval * arg,const char * key,size_t key_len,double d)1728 ZEND_API void add_assoc_double_ex(zval *arg, const char *key, size_t key_len, double d) /* {{{ */
1729 {
1730 	zval tmp;
1731 
1732 	ZVAL_DOUBLE(&tmp, d);
1733 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1734 }
1735 /* }}} */
1736 
add_assoc_str_ex(zval * arg,const char * key,size_t key_len,zend_string * str)1737 ZEND_API void add_assoc_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str) /* {{{ */
1738 {
1739 	zval tmp;
1740 
1741 	ZVAL_STR(&tmp, str);
1742 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1743 }
1744 /* }}} */
1745 
add_assoc_string_ex(zval * arg,const char * key,size_t key_len,const char * str)1746 ZEND_API void add_assoc_string_ex(zval *arg, const char *key, size_t key_len, const char *str) /* {{{ */
1747 {
1748 	zval tmp;
1749 
1750 	ZVAL_STRING(&tmp, str);
1751 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1752 }
1753 /* }}} */
1754 
add_assoc_stringl_ex(zval * arg,const char * key,size_t key_len,const char * str,size_t length)1755 ZEND_API void add_assoc_stringl_ex(zval *arg, const char *key, size_t key_len, const char *str, size_t length) /* {{{ */
1756 {
1757 	zval tmp;
1758 
1759 	ZVAL_STRINGL(&tmp, str, length);
1760 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1761 }
1762 /* }}} */
1763 
add_assoc_array_ex(zval * arg,const char * key,size_t key_len,zend_array * arr)1764 ZEND_API void add_assoc_array_ex(zval *arg, const char *key, size_t key_len, zend_array *arr) /* {{{ */
1765 {
1766 	zval tmp;
1767 
1768 	ZVAL_ARR(&tmp, arr);
1769 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1770 }
1771 /* }}} */
1772 
add_assoc_object_ex(zval * arg,const char * key,size_t key_len,zend_object * obj)1773 ZEND_API void add_assoc_object_ex(zval *arg, const char *key, size_t key_len, zend_object *obj) /* {{{ */
1774 {
1775 	zval tmp;
1776 
1777 	ZVAL_OBJ(&tmp, obj);
1778 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1779 }
1780 /* }}} */
1781 
add_assoc_reference_ex(zval * arg,const char * key,size_t key_len,zend_reference * ref)1782 ZEND_API void add_assoc_reference_ex(zval *arg, const char *key, size_t key_len, zend_reference *ref) /* {{{ */
1783 {
1784 	zval tmp;
1785 
1786 	ZVAL_REF(&tmp, ref);
1787 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1788 }
1789 /* }}} */
1790 
add_assoc_zval_ex(zval * arg,const char * key,size_t key_len,zval * value)1791 ZEND_API void add_assoc_zval_ex(zval *arg, const char *key, size_t key_len, zval *value) /* {{{ */
1792 {
1793 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, value);
1794 }
1795 /* }}} */
1796 
add_index_long(zval * arg,zend_ulong index,zend_long n)1797 ZEND_API void add_index_long(zval *arg, zend_ulong index, zend_long n) /* {{{ */
1798 {
1799 	zval tmp;
1800 
1801 	ZVAL_LONG(&tmp, n);
1802 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1803 }
1804 /* }}} */
1805 
add_index_null(zval * arg,zend_ulong index)1806 ZEND_API void add_index_null(zval *arg, zend_ulong index) /* {{{ */
1807 {
1808 	zval tmp;
1809 
1810 	ZVAL_NULL(&tmp);
1811 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1812 }
1813 /* }}} */
1814 
add_index_bool(zval * arg,zend_ulong index,bool b)1815 ZEND_API void add_index_bool(zval *arg, zend_ulong index, bool b) /* {{{ */
1816 {
1817 	zval tmp;
1818 
1819 	ZVAL_BOOL(&tmp, b);
1820 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1821 }
1822 /* }}} */
1823 
add_index_resource(zval * arg,zend_ulong index,zend_resource * r)1824 ZEND_API void add_index_resource(zval *arg, zend_ulong index, zend_resource *r) /* {{{ */
1825 {
1826 	zval tmp;
1827 
1828 	ZVAL_RES(&tmp, r);
1829 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1830 }
1831 /* }}} */
1832 
add_index_double(zval * arg,zend_ulong index,double d)1833 ZEND_API void add_index_double(zval *arg, zend_ulong index, double d) /* {{{ */
1834 {
1835 	zval tmp;
1836 
1837 	ZVAL_DOUBLE(&tmp, d);
1838 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1839 }
1840 /* }}} */
1841 
add_index_str(zval * arg,zend_ulong index,zend_string * str)1842 ZEND_API void add_index_str(zval *arg, zend_ulong index, zend_string *str) /* {{{ */
1843 {
1844 	zval tmp;
1845 
1846 	ZVAL_STR(&tmp, str);
1847 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1848 }
1849 /* }}} */
1850 
add_index_string(zval * arg,zend_ulong index,const char * str)1851 ZEND_API void add_index_string(zval *arg, zend_ulong index, const char *str) /* {{{ */
1852 {
1853 	zval tmp;
1854 
1855 	ZVAL_STRING(&tmp, str);
1856 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1857 }
1858 /* }}} */
1859 
add_index_stringl(zval * arg,zend_ulong index,const char * str,size_t length)1860 ZEND_API void add_index_stringl(zval *arg, zend_ulong index, const char *str, size_t length) /* {{{ */
1861 {
1862 	zval tmp;
1863 
1864 	ZVAL_STRINGL(&tmp, str, length);
1865 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1866 }
1867 /* }}} */
1868 
add_index_array(zval * arg,zend_ulong index,zend_array * arr)1869 ZEND_API void add_index_array(zval *arg, zend_ulong index, zend_array *arr) /* {{{ */
1870 {
1871 	zval tmp;
1872 
1873 	ZVAL_ARR(&tmp, arr);
1874 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1875 }
1876 /* }}} */
1877 
add_index_object(zval * arg,zend_ulong index,zend_object * obj)1878 ZEND_API void add_index_object(zval *arg, zend_ulong index, zend_object *obj) /* {{{ */
1879 {
1880 	zval tmp;
1881 
1882 	ZVAL_OBJ(&tmp, obj);
1883 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1884 }
1885 /* }}} */
1886 
add_index_reference(zval * arg,zend_ulong index,zend_reference * ref)1887 ZEND_API void add_index_reference(zval *arg, zend_ulong index, zend_reference *ref) /* {{{ */
1888 {
1889 	zval tmp;
1890 
1891 	ZVAL_REF(&tmp, ref);
1892 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1893 }
1894 /* }}} */
1895 
add_next_index_long(zval * arg,zend_long n)1896 ZEND_API zend_result add_next_index_long(zval *arg, zend_long n) /* {{{ */
1897 {
1898 	zval tmp;
1899 
1900 	ZVAL_LONG(&tmp, n);
1901 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1902 }
1903 /* }}} */
1904 
add_next_index_null(zval * arg)1905 ZEND_API zend_result add_next_index_null(zval *arg) /* {{{ */
1906 {
1907 	zval tmp;
1908 
1909 	ZVAL_NULL(&tmp);
1910 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1911 }
1912 /* }}} */
1913 
add_next_index_bool(zval * arg,bool b)1914 ZEND_API zend_result add_next_index_bool(zval *arg, bool b) /* {{{ */
1915 {
1916 	zval tmp;
1917 
1918 	ZVAL_BOOL(&tmp, b);
1919 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1920 }
1921 /* }}} */
1922 
add_next_index_resource(zval * arg,zend_resource * r)1923 ZEND_API zend_result add_next_index_resource(zval *arg, zend_resource *r) /* {{{ */
1924 {
1925 	zval tmp;
1926 
1927 	ZVAL_RES(&tmp, r);
1928 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1929 }
1930 /* }}} */
1931 
add_next_index_double(zval * arg,double d)1932 ZEND_API zend_result add_next_index_double(zval *arg, double d) /* {{{ */
1933 {
1934 	zval tmp;
1935 
1936 	ZVAL_DOUBLE(&tmp, d);
1937 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1938 }
1939 /* }}} */
1940 
add_next_index_str(zval * arg,zend_string * str)1941 ZEND_API zend_result add_next_index_str(zval *arg, zend_string *str) /* {{{ */
1942 {
1943 	zval tmp;
1944 
1945 	ZVAL_STR(&tmp, str);
1946 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1947 }
1948 /* }}} */
1949 
add_next_index_string(zval * arg,const char * str)1950 ZEND_API zend_result add_next_index_string(zval *arg, const char *str) /* {{{ */
1951 {
1952 	zval tmp;
1953 
1954 	ZVAL_STRING(&tmp, str);
1955 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1956 }
1957 /* }}} */
1958 
add_next_index_stringl(zval * arg,const char * str,size_t length)1959 ZEND_API zend_result add_next_index_stringl(zval *arg, const char *str, size_t length) /* {{{ */
1960 {
1961 	zval tmp;
1962 
1963 	ZVAL_STRINGL(&tmp, str, length);
1964 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1965 }
1966 /* }}} */
1967 
add_next_index_array(zval * arg,zend_array * arr)1968 ZEND_API zend_result add_next_index_array(zval *arg, zend_array *arr) /* {{{ */
1969 {
1970 	zval tmp;
1971 
1972 	ZVAL_ARR(&tmp, arr);
1973 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1974 }
1975 /* }}} */
1976 
add_next_index_object(zval * arg,zend_object * obj)1977 ZEND_API zend_result add_next_index_object(zval *arg, zend_object *obj) /* {{{ */
1978 {
1979 	zval tmp;
1980 
1981 	ZVAL_OBJ(&tmp, obj);
1982 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1983 }
1984 /* }}} */
1985 
add_next_index_reference(zval * arg,zend_reference * ref)1986 ZEND_API zend_result add_next_index_reference(zval *arg, zend_reference *ref) /* {{{ */
1987 {
1988 	zval tmp;
1989 
1990 	ZVAL_REF(&tmp, ref);
1991 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1992 }
1993 /* }}} */
1994 
array_set_zval_key(HashTable * ht,zval * key,zval * value)1995 ZEND_API zend_result array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */
1996 {
1997 	zval *result;
1998 
1999 	switch (Z_TYPE_P(key)) {
2000 		case IS_STRING:
2001 			result = zend_symtable_update(ht, Z_STR_P(key), value);
2002 			break;
2003 		case IS_NULL:
2004 			result = zend_hash_update(ht, ZSTR_EMPTY_ALLOC(), value);
2005 			break;
2006 		case IS_RESOURCE:
2007 			zend_use_resource_as_offset(key);
2008 			result = zend_hash_index_update(ht, Z_RES_HANDLE_P(key), value);
2009 			break;
2010 		case IS_FALSE:
2011 			result = zend_hash_index_update(ht, 0, value);
2012 			break;
2013 		case IS_TRUE:
2014 			result = zend_hash_index_update(ht, 1, value);
2015 			break;
2016 		case IS_LONG:
2017 			result = zend_hash_index_update(ht, Z_LVAL_P(key), value);
2018 			break;
2019 		case IS_DOUBLE:
2020 			result = zend_hash_index_update(ht, zend_dval_to_lval_safe(Z_DVAL_P(key)), value);
2021 			break;
2022 		default:
2023 			zend_type_error("Illegal offset type");
2024 			result = NULL;
2025 	}
2026 
2027 	if (result) {
2028 		Z_TRY_ADDREF_P(result);
2029 		return SUCCESS;
2030 	} else {
2031 		return FAILURE;
2032 	}
2033 }
2034 /* }}} */
2035 
add_property_long_ex(zval * arg,const char * key,size_t key_len,zend_long n)2036 ZEND_API void add_property_long_ex(zval *arg, const char *key, size_t key_len, zend_long n) /* {{{ */
2037 {
2038 	zval tmp;
2039 
2040 	ZVAL_LONG(&tmp, n);
2041 	add_property_zval_ex(arg, key, key_len, &tmp);
2042 }
2043 /* }}} */
2044 
add_property_bool_ex(zval * arg,const char * key,size_t key_len,zend_long b)2045 ZEND_API void add_property_bool_ex(zval *arg, const char *key, size_t key_len, zend_long b) /* {{{ */
2046 {
2047 	zval tmp;
2048 
2049 	ZVAL_BOOL(&tmp, b);
2050 	add_property_zval_ex(arg, key, key_len, &tmp);
2051 }
2052 /* }}} */
2053 
add_property_null_ex(zval * arg,const char * key,size_t key_len)2054 ZEND_API void add_property_null_ex(zval *arg, const char *key, size_t key_len) /* {{{ */
2055 {
2056 	zval tmp;
2057 
2058 	ZVAL_NULL(&tmp);
2059 	add_property_zval_ex(arg, key, key_len, &tmp);
2060 }
2061 /* }}} */
2062 
add_property_resource_ex(zval * arg,const char * key,size_t key_len,zend_resource * r)2063 ZEND_API void add_property_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r) /* {{{ */
2064 {
2065 	zval tmp;
2066 
2067 	ZVAL_RES(&tmp, r);
2068 	add_property_zval_ex(arg, key, key_len, &tmp);
2069 	zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2070 }
2071 /* }}} */
2072 
add_property_double_ex(zval * arg,const char * key,size_t key_len,double d)2073 ZEND_API void add_property_double_ex(zval *arg, const char *key, size_t key_len, double d) /* {{{ */
2074 {
2075 	zval tmp;
2076 
2077 	ZVAL_DOUBLE(&tmp, d);
2078 	add_property_zval_ex(arg, key, key_len, &tmp);
2079 }
2080 /* }}} */
2081 
add_property_str_ex(zval * arg,const char * key,size_t key_len,zend_string * str)2082 ZEND_API void add_property_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str) /* {{{ */
2083 {
2084 	zval tmp;
2085 
2086 	ZVAL_STR(&tmp, str);
2087 	add_property_zval_ex(arg, key, key_len, &tmp);
2088 	zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2089 }
2090 /* }}} */
2091 
add_property_string_ex(zval * arg,const char * key,size_t key_len,const char * str)2092 ZEND_API void add_property_string_ex(zval *arg, const char *key, size_t key_len, const char *str) /* {{{ */
2093 {
2094 	zval tmp;
2095 
2096 	ZVAL_STRING(&tmp, str);
2097 	add_property_zval_ex(arg, key, key_len, &tmp);
2098 	zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2099 }
2100 /* }}} */
2101 
add_property_stringl_ex(zval * arg,const char * key,size_t key_len,const char * str,size_t length)2102 ZEND_API void add_property_stringl_ex(zval *arg, const char *key, size_t key_len, const char *str, size_t length) /* {{{ */
2103 {
2104 	zval tmp;
2105 
2106 	ZVAL_STRINGL(&tmp, str, length);
2107 	add_property_zval_ex(arg, key, key_len, &tmp);
2108 	zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2109 }
2110 /* }}} */
2111 
add_property_array_ex(zval * arg,const char * key,size_t key_len,zend_array * arr)2112 ZEND_API void add_property_array_ex(zval *arg, const char *key, size_t key_len, zend_array *arr) /* {{{ */
2113 {
2114 	zval tmp;
2115 
2116 	ZVAL_ARR(&tmp, arr);
2117 	add_property_zval_ex(arg, key, key_len, &tmp);
2118 	zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2119 }
2120 /* }}} */
2121 
add_property_object_ex(zval * arg,const char * key,size_t key_len,zend_object * obj)2122 ZEND_API void add_property_object_ex(zval *arg, const char *key, size_t key_len, zend_object *obj) /* {{{ */
2123 {
2124 	zval tmp;
2125 
2126 	ZVAL_OBJ(&tmp, obj);
2127 	add_property_zval_ex(arg, key, key_len, &tmp);
2128 	zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2129 }
2130 /* }}} */
2131 
add_property_reference_ex(zval * arg,const char * key,size_t key_len,zend_reference * ref)2132 ZEND_API void add_property_reference_ex(zval *arg, const char *key, size_t key_len, zend_reference *ref) /* {{{ */
2133 {
2134 	zval tmp;
2135 
2136 	ZVAL_REF(&tmp, ref);
2137 	add_property_zval_ex(arg, key, key_len, &tmp);
2138 	zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2139 }
2140 /* }}} */
2141 
add_property_zval_ex(zval * arg,const char * key,size_t key_len,zval * value)2142 ZEND_API void add_property_zval_ex(zval *arg, const char *key, size_t key_len, zval *value) /* {{{ */
2143 {
2144 	zend_string *str;
2145 
2146 	str = zend_string_init(key, key_len, 0);
2147 	Z_OBJ_HANDLER_P(arg, write_property)(Z_OBJ_P(arg), str, value, NULL);
2148 	zend_string_release_ex(str, 0);
2149 }
2150 /* }}} */
2151 
zend_startup_module_ex(zend_module_entry * module)2152 ZEND_API zend_result zend_startup_module_ex(zend_module_entry *module) /* {{{ */
2153 {
2154 	size_t name_len;
2155 	zend_string *lcname;
2156 
2157 	if (module->module_started) {
2158 		return SUCCESS;
2159 	}
2160 	module->module_started = 1;
2161 
2162 	/* Check module dependencies */
2163 	if (module->deps) {
2164 		const zend_module_dep *dep = module->deps;
2165 
2166 		while (dep->name) {
2167 			if (dep->type == MODULE_DEP_REQUIRED) {
2168 				zend_module_entry *req_mod;
2169 
2170 				name_len = strlen(dep->name);
2171 				lcname = zend_string_alloc(name_len, 0);
2172 				zend_str_tolower_copy(ZSTR_VAL(lcname), dep->name, name_len);
2173 
2174 				if ((req_mod = zend_hash_find_ptr(&module_registry, lcname)) == NULL || !req_mod->module_started) {
2175 					zend_string_efree(lcname);
2176 					/* TODO: Check version relationship */
2177 					zend_error(E_CORE_WARNING, "Cannot load module \"%s\" because required module \"%s\" is not loaded", module->name, dep->name);
2178 					module->module_started = 0;
2179 					return FAILURE;
2180 				}
2181 				zend_string_efree(lcname);
2182 			}
2183 			++dep;
2184 		}
2185 	}
2186 
2187 	/* Initialize module globals */
2188 	if (module->globals_size) {
2189 #ifdef ZTS
2190 		ts_allocate_id(module->globals_id_ptr, module->globals_size, (ts_allocate_ctor) module->globals_ctor, (ts_allocate_dtor) module->globals_dtor);
2191 #else
2192 		if (module->globals_ctor) {
2193 			module->globals_ctor(module->globals_ptr);
2194 		}
2195 #endif
2196 	}
2197 	if (module->module_startup_func) {
2198 		EG(current_module) = module;
2199 		if (module->module_startup_func(module->type, module->module_number)==FAILURE) {
2200 			zend_error_noreturn(E_CORE_ERROR,"Unable to start %s module", module->name);
2201 			EG(current_module) = NULL;
2202 			return FAILURE;
2203 		}
2204 		EG(current_module) = NULL;
2205 	}
2206 	return SUCCESS;
2207 }
2208 /* }}} */
2209 
zend_startup_module_zval(zval * zv)2210 static int zend_startup_module_zval(zval *zv) /* {{{ */
2211 {
2212 	zend_module_entry *module = Z_PTR_P(zv);
2213 
2214 	return (zend_startup_module_ex(module) == SUCCESS) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
2215 }
2216 /* }}} */
2217 
zend_sort_modules(void * base,size_t count,size_t siz,compare_func_t compare,swap_func_t swp)2218 static void zend_sort_modules(void *base, size_t count, size_t siz, compare_func_t compare, swap_func_t swp) /* {{{ */
2219 {
2220 	Bucket *b1 = base;
2221 	Bucket *b2;
2222 	Bucket *end = b1 + count;
2223 	Bucket tmp;
2224 	zend_module_entry *m, *r;
2225 
2226 	while (b1 < end) {
2227 try_again:
2228 		m = (zend_module_entry*)Z_PTR(b1->val);
2229 		if (!m->module_started && m->deps) {
2230 			const zend_module_dep *dep = m->deps;
2231 			while (dep->name) {
2232 				if (dep->type == MODULE_DEP_REQUIRED || dep->type == MODULE_DEP_OPTIONAL) {
2233 					b2 = b1 + 1;
2234 					while (b2 < end) {
2235 						r = (zend_module_entry*)Z_PTR(b2->val);
2236 						if (strcasecmp(dep->name, r->name) == 0) {
2237 							tmp = *b1;
2238 							*b1 = *b2;
2239 							*b2 = tmp;
2240 							goto try_again;
2241 						}
2242 						b2++;
2243 					}
2244 				}
2245 				dep++;
2246 			}
2247 		}
2248 		b1++;
2249 	}
2250 }
2251 /* }}} */
2252 
zend_collect_module_handlers(void)2253 ZEND_API void zend_collect_module_handlers(void) /* {{{ */
2254 {
2255 	zend_module_entry *module;
2256 	int startup_count = 0;
2257 	int shutdown_count = 0;
2258 	int post_deactivate_count = 0;
2259 	zend_class_entry *ce;
2260 	int class_count = 0;
2261 
2262 	/* Collect extensions with request startup/shutdown handlers */
2263 	ZEND_HASH_FOREACH_PTR(&module_registry, module) {
2264 		if (module->request_startup_func) {
2265 			startup_count++;
2266 		}
2267 		if (module->request_shutdown_func) {
2268 			shutdown_count++;
2269 		}
2270 		if (module->post_deactivate_func) {
2271 			post_deactivate_count++;
2272 		}
2273 	} ZEND_HASH_FOREACH_END();
2274 	module_request_startup_handlers = (zend_module_entry**)realloc(
2275 		module_request_startup_handlers,
2276 	    sizeof(zend_module_entry*) *
2277 		(startup_count + 1 +
2278 		 shutdown_count + 1 +
2279 		 post_deactivate_count + 1));
2280 	module_request_startup_handlers[startup_count] = NULL;
2281 	module_request_shutdown_handlers = module_request_startup_handlers + startup_count + 1;
2282 	module_request_shutdown_handlers[shutdown_count] = NULL;
2283 	module_post_deactivate_handlers = module_request_shutdown_handlers + shutdown_count + 1;
2284 	module_post_deactivate_handlers[post_deactivate_count] = NULL;
2285 	startup_count = 0;
2286 
2287 	ZEND_HASH_FOREACH_PTR(&module_registry, module) {
2288 		if (module->request_startup_func) {
2289 			module_request_startup_handlers[startup_count++] = module;
2290 		}
2291 		if (module->request_shutdown_func) {
2292 			module_request_shutdown_handlers[--shutdown_count] = module;
2293 		}
2294 		if (module->post_deactivate_func) {
2295 			module_post_deactivate_handlers[--post_deactivate_count] = module;
2296 		}
2297 	} ZEND_HASH_FOREACH_END();
2298 
2299 	/* Collect internal classes with static members */
2300 	ZEND_HASH_FOREACH_PTR(CG(class_table), ce) {
2301 		if (ce->type == ZEND_INTERNAL_CLASS &&
2302 		    ce->default_static_members_count > 0) {
2303 		    class_count++;
2304 		}
2305 	} ZEND_HASH_FOREACH_END();
2306 
2307 	class_cleanup_handlers = (zend_class_entry**)realloc(
2308 		class_cleanup_handlers,
2309 		sizeof(zend_class_entry*) *
2310 		(class_count + 1));
2311 	class_cleanup_handlers[class_count] = NULL;
2312 
2313 	if (class_count) {
2314 		ZEND_HASH_FOREACH_PTR(CG(class_table), ce) {
2315 			if (ce->type == ZEND_INTERNAL_CLASS &&
2316 			    ce->default_static_members_count > 0) {
2317 			    class_cleanup_handlers[--class_count] = ce;
2318 			}
2319 		} ZEND_HASH_FOREACH_END();
2320 	}
2321 }
2322 /* }}} */
2323 
zend_startup_modules(void)2324 ZEND_API void zend_startup_modules(void) /* {{{ */
2325 {
2326 	zend_hash_sort_ex(&module_registry, zend_sort_modules, NULL, 0);
2327 	zend_hash_apply(&module_registry, zend_startup_module_zval);
2328 }
2329 /* }}} */
2330 
zend_destroy_modules(void)2331 ZEND_API void zend_destroy_modules(void) /* {{{ */
2332 {
2333 	free(class_cleanup_handlers);
2334 	class_cleanup_handlers = NULL;
2335 	free(module_request_startup_handlers);
2336 	module_request_startup_handlers = NULL;
2337 	zend_hash_graceful_reverse_destroy(&module_registry);
2338 }
2339 /* }}} */
2340 
zend_register_module_ex(zend_module_entry * module)2341 ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module) /* {{{ */
2342 {
2343 	size_t name_len;
2344 	zend_string *lcname;
2345 	zend_module_entry *module_ptr;
2346 
2347 	if (!module) {
2348 		return NULL;
2349 	}
2350 
2351 #if 0
2352 	zend_printf("%s: Registering module %d\n", module->name, module->module_number);
2353 #endif
2354 
2355 	/* Check module dependencies */
2356 	if (module->deps) {
2357 		const zend_module_dep *dep = module->deps;
2358 
2359 		while (dep->name) {
2360 			if (dep->type == MODULE_DEP_CONFLICTS) {
2361 				name_len = strlen(dep->name);
2362 				lcname = zend_string_alloc(name_len, 0);
2363 				zend_str_tolower_copy(ZSTR_VAL(lcname), dep->name, name_len);
2364 
2365 				if (zend_hash_exists(&module_registry, lcname) || zend_get_extension(dep->name)) {
2366 					zend_string_efree(lcname);
2367 					/* TODO: Check version relationship */
2368 					zend_error(E_CORE_WARNING, "Cannot load module \"%s\" because conflicting module \"%s\" is already loaded", module->name, dep->name);
2369 					return NULL;
2370 				}
2371 				zend_string_efree(lcname);
2372 			}
2373 			++dep;
2374 		}
2375 	}
2376 
2377 	name_len = strlen(module->name);
2378 	lcname = zend_string_alloc(name_len, module->type == MODULE_PERSISTENT);
2379 	zend_str_tolower_copy(ZSTR_VAL(lcname), module->name, name_len);
2380 
2381 	lcname = zend_new_interned_string(lcname);
2382 	if ((module_ptr = zend_hash_add_mem(&module_registry, lcname, module, sizeof(zend_module_entry))) == NULL) {
2383 		zend_error(E_CORE_WARNING, "Module \"%s\" is already loaded", module->name);
2384 		zend_string_release(lcname);
2385 		return NULL;
2386 	}
2387 	module = module_ptr;
2388 	EG(current_module) = module;
2389 
2390 	if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type)==FAILURE) {
2391 		zend_hash_del(&module_registry, lcname);
2392 		zend_string_release(lcname);
2393 		EG(current_module) = NULL;
2394 		zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name);
2395 		return NULL;
2396 	}
2397 
2398 	EG(current_module) = NULL;
2399 	zend_string_release(lcname);
2400 	return module;
2401 }
2402 /* }}} */
2403 
zend_register_internal_module(zend_module_entry * module)2404 ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *module) /* {{{ */
2405 {
2406 	module->module_number = zend_next_free_module();
2407 	module->type = MODULE_PERSISTENT;
2408 	return zend_register_module_ex(module);
2409 }
2410 /* }}} */
2411 
zend_check_magic_method_args(uint32_t num_args,const zend_class_entry * ce,const zend_function * fptr,int error_type)2412 static void zend_check_magic_method_args(
2413 		uint32_t num_args, const zend_class_entry *ce, const zend_function *fptr, int error_type)
2414 {
2415 	if (fptr->common.num_args != num_args) {
2416 		if (num_args == 0) {
2417 			zend_error(error_type, "Method %s::%s() cannot take arguments",
2418 				ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2419 		} else if (num_args == 1) {
2420 			zend_error(error_type, "Method %s::%s() must take exactly 1 argument",
2421 				ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2422 		} else {
2423 			zend_error(error_type, "Method %s::%s() must take exactly %" PRIu32 " arguments",
2424 				ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name), num_args);
2425 		}
2426 		return;
2427 	}
2428 	for (uint32_t i = 0; i < num_args; i++) {
2429 		if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, i + 1)) {
2430 			zend_error(error_type, "Method %s::%s() cannot take arguments by reference",
2431 				ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2432 			return;
2433 		}
2434 	}
2435 }
2436 
zend_check_magic_method_arg_type(uint32_t arg_num,const zend_class_entry * ce,const zend_function * fptr,int error_type,int arg_type)2437 static void zend_check_magic_method_arg_type(uint32_t arg_num, const zend_class_entry *ce, const zend_function *fptr, int error_type, int arg_type)
2438 {
2439 		if (
2440 			ZEND_TYPE_IS_SET(fptr->common.arg_info[arg_num].type)
2441 			 && !(ZEND_TYPE_FULL_MASK(fptr->common.arg_info[arg_num].type) & arg_type)
2442 		) {
2443 			zend_error(error_type, "%s::%s(): Parameter #%d ($%s) must be of type %s when declared",
2444 				ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name),
2445 				arg_num + 1, ZSTR_VAL(fptr->common.arg_info[arg_num].name),
2446 				ZSTR_VAL(zend_type_to_string((zend_type) ZEND_TYPE_INIT_MASK(arg_type))));
2447 		}
2448 }
2449 
zend_check_magic_method_return_type(const zend_class_entry * ce,const zend_function * fptr,int error_type,int return_type)2450 static void zend_check_magic_method_return_type(const zend_class_entry *ce, const zend_function *fptr, int error_type, int return_type)
2451 {
2452 	if (!(fptr->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
2453 		/* For backwards compatibility reasons, do not enforce the return type if it is not set. */
2454 		return;
2455 	}
2456 
2457 	if (ZEND_TYPE_PURE_MASK(fptr->common.arg_info[-1].type) & MAY_BE_NEVER) {
2458 		/* It is always legal to specify the never type. */
2459 		return;
2460 	}
2461 
2462 	bool is_complex_type = ZEND_TYPE_IS_COMPLEX(fptr->common.arg_info[-1].type);
2463 	uint32_t extra_types = ZEND_TYPE_PURE_MASK(fptr->common.arg_info[-1].type) & ~return_type;
2464 	if (extra_types & MAY_BE_STATIC) {
2465 		extra_types &= ~MAY_BE_STATIC;
2466 		is_complex_type = true;
2467 	}
2468 
2469 	if (extra_types || (is_complex_type && return_type != MAY_BE_OBJECT)) {
2470 		zend_error(error_type, "%s::%s(): Return type must be %s when declared",
2471 			ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name),
2472 			ZSTR_VAL(zend_type_to_string((zend_type) ZEND_TYPE_INIT_MASK(return_type))));
2473 	}
2474 }
2475 
zend_check_magic_method_non_static(const zend_class_entry * ce,const zend_function * fptr,int error_type)2476 static void zend_check_magic_method_non_static(
2477 		const zend_class_entry *ce, const zend_function *fptr, int error_type)
2478 {
2479 	if (fptr->common.fn_flags & ZEND_ACC_STATIC) {
2480 		zend_error(error_type, "Method %s::%s() cannot be static",
2481 			ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2482 	}
2483 }
2484 
zend_check_magic_method_static(const zend_class_entry * ce,const zend_function * fptr,int error_type)2485 static void zend_check_magic_method_static(
2486 		const zend_class_entry *ce, const zend_function *fptr, int error_type)
2487 {
2488 	if (!(fptr->common.fn_flags & ZEND_ACC_STATIC)) {
2489 		zend_error(error_type, "Method %s::%s() must be static",
2490 			ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2491 	}
2492 }
2493 
zend_check_magic_method_public(const zend_class_entry * ce,const zend_function * fptr,int error_type)2494 static void zend_check_magic_method_public(
2495 		const zend_class_entry *ce, const zend_function *fptr, int error_type)
2496 {
2497 	// TODO: Remove this warning after adding proper visibility handling.
2498 	if (!(fptr->common.fn_flags & ZEND_ACC_PUBLIC)) {
2499 		zend_error(E_WARNING, "The magic method %s::%s() must have public visibility",
2500 			ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2501 	}
2502 }
2503 
zend_check_magic_method_no_return_type(const zend_class_entry * ce,const zend_function * fptr,int error_type)2504 static void zend_check_magic_method_no_return_type(
2505 		const zend_class_entry *ce, const zend_function *fptr, int error_type)
2506 {
2507 	if (fptr->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
2508 		zend_error_noreturn(error_type, "Method %s::%s() cannot declare a return type",
2509 			ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2510 	}
2511 }
2512 
zend_check_magic_method_implementation(const zend_class_entry * ce,const zend_function * fptr,zend_string * lcname,int error_type)2513 ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, zend_string *lcname, int error_type) /* {{{ */
2514 {
2515 	if (ZSTR_VAL(fptr->common.function_name)[0] != '_'
2516 	 || ZSTR_VAL(fptr->common.function_name)[1] != '_') {
2517 		return;
2518 	}
2519 
2520 	if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
2521 		zend_check_magic_method_non_static(ce, fptr, error_type);
2522 		zend_check_magic_method_no_return_type(ce, fptr, error_type);
2523 	} else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) {
2524 		zend_check_magic_method_args(0, ce, fptr, error_type);
2525 		zend_check_magic_method_non_static(ce, fptr, error_type);
2526 		zend_check_magic_method_no_return_type(ce, fptr, error_type);
2527 	} else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) {
2528 		zend_check_magic_method_args(0, ce, fptr, error_type);
2529 		zend_check_magic_method_non_static(ce, fptr, error_type);
2530 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
2531 	} else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) {
2532 		zend_check_magic_method_args(1, ce, fptr, error_type);
2533 		zend_check_magic_method_non_static(ce, fptr, error_type);
2534 		zend_check_magic_method_public(ce, fptr, error_type);
2535 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2536 	} else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) {
2537 		zend_check_magic_method_args(2, ce, fptr, error_type);
2538 		zend_check_magic_method_non_static(ce, fptr, error_type);
2539 		zend_check_magic_method_public(ce, fptr, error_type);
2540 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2541 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
2542 	} else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) {
2543 		zend_check_magic_method_args(1, ce, fptr, error_type);
2544 		zend_check_magic_method_non_static(ce, fptr, error_type);
2545 		zend_check_magic_method_public(ce, fptr, error_type);
2546 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2547 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
2548 	} else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
2549 		zend_check_magic_method_args(1, ce, fptr, error_type);
2550 		zend_check_magic_method_non_static(ce, fptr, error_type);
2551 		zend_check_magic_method_public(ce, fptr, error_type);
2552 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2553 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_BOOL);
2554 	} else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
2555 		zend_check_magic_method_args(2, ce, fptr, error_type);
2556 		zend_check_magic_method_non_static(ce, fptr, error_type);
2557 		zend_check_magic_method_public(ce, fptr, error_type);
2558 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2559 		zend_check_magic_method_arg_type(1, ce, fptr, error_type, MAY_BE_ARRAY);
2560 	} else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) {
2561 		zend_check_magic_method_args(2, ce, fptr, error_type);
2562 		zend_check_magic_method_static(ce, fptr, error_type);
2563 		zend_check_magic_method_public(ce, fptr, error_type);
2564 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2565 		zend_check_magic_method_arg_type(1, ce, fptr, error_type, MAY_BE_ARRAY);
2566 	} else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
2567 		zend_check_magic_method_args(0, ce, fptr, error_type);
2568 		zend_check_magic_method_non_static(ce, fptr, error_type);
2569 		zend_check_magic_method_public(ce, fptr, error_type);
2570 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_STRING);
2571 	} else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
2572 		zend_check_magic_method_args(0, ce, fptr, error_type);
2573 		zend_check_magic_method_non_static(ce, fptr, error_type);
2574 		zend_check_magic_method_public(ce, fptr, error_type);
2575 		zend_check_magic_method_return_type(ce, fptr, error_type, (MAY_BE_ARRAY | MAY_BE_NULL));
2576 	} else if (zend_string_equals_literal(lcname, "__serialize")) {
2577 		zend_check_magic_method_args(0, ce, fptr, error_type);
2578 		zend_check_magic_method_non_static(ce, fptr, error_type);
2579 		zend_check_magic_method_public(ce, fptr, error_type);
2580 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_ARRAY);
2581 	} else if (zend_string_equals_literal(lcname, "__unserialize")) {
2582 		zend_check_magic_method_args(1, ce, fptr, error_type);
2583 		zend_check_magic_method_non_static(ce, fptr, error_type);
2584 		zend_check_magic_method_public(ce, fptr, error_type);
2585 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_ARRAY);
2586 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
2587 	} else if (zend_string_equals_literal(lcname, "__set_state")) {
2588 		zend_check_magic_method_args(1, ce, fptr, error_type);
2589 		zend_check_magic_method_static(ce, fptr, error_type);
2590 		zend_check_magic_method_public(ce, fptr, error_type);
2591 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_ARRAY);
2592 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_OBJECT);
2593 	} else if (zend_string_equals_literal(lcname, "__invoke")) {
2594 		zend_check_magic_method_non_static(ce, fptr, error_type);
2595 		zend_check_magic_method_public(ce, fptr, error_type);
2596 	} else if (zend_string_equals_literal(lcname, "__sleep")) {
2597 		zend_check_magic_method_args(0, ce, fptr, error_type);
2598 		zend_check_magic_method_non_static(ce, fptr, error_type);
2599 		zend_check_magic_method_public(ce, fptr, error_type);
2600 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_ARRAY);
2601 	} else if (zend_string_equals_literal(lcname, "__wakeup")) {
2602 		zend_check_magic_method_args(0, ce, fptr, error_type);
2603 		zend_check_magic_method_non_static(ce, fptr, error_type);
2604 		zend_check_magic_method_public(ce, fptr, error_type);
2605 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
2606 	}
2607 }
2608 /* }}} */
2609 
zend_add_magic_method(zend_class_entry * ce,zend_function * fptr,zend_string * lcname)2610 ZEND_API void zend_add_magic_method(zend_class_entry *ce, zend_function *fptr, zend_string *lcname)
2611 {
2612 	if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') {
2613 		/* pass */
2614 	} else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) {
2615 		ce->clone = fptr;
2616 	} else if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
2617 		ce->constructor = fptr;
2618 		ce->constructor->common.fn_flags |= ZEND_ACC_CTOR;
2619 	} else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) {
2620 		ce->destructor = fptr;
2621 	} else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) {
2622 		ce->__get = fptr;
2623 		ce->ce_flags |= ZEND_ACC_USE_GUARDS;
2624 	} else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) {
2625 		ce->__set = fptr;
2626 		ce->ce_flags |= ZEND_ACC_USE_GUARDS;
2627 	} else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
2628 		ce->__call = fptr;
2629 	} else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) {
2630 		ce->__unset = fptr;
2631 		ce->ce_flags |= ZEND_ACC_USE_GUARDS;
2632 	} else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
2633 		ce->__isset = fptr;
2634 		ce->ce_flags |= ZEND_ACC_USE_GUARDS;
2635 	} else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) {
2636 		ce->__callstatic = fptr;
2637 	} else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
2638 		ce->__tostring = fptr;
2639 	} else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
2640 		ce->__debugInfo = fptr;
2641 	} else if (zend_string_equals_literal(lcname, "__serialize")) {
2642 		ce->__serialize = fptr;
2643 	} else if (zend_string_equals_literal(lcname, "__unserialize")) {
2644 		ce->__unserialize = fptr;
2645 	}
2646 }
2647 
2648 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arg_info_toString, 0, 0, IS_STRING, 0)
ZEND_END_ARG_INFO()2649 ZEND_END_ARG_INFO()
2650 
2651 /* registers all functions in *library_functions in the function hash */
2652 ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type) /* {{{ */
2653 {
2654 	const zend_function_entry *ptr = functions;
2655 	zend_function function, *reg_function;
2656 	zend_internal_function *internal_function = (zend_internal_function *)&function;
2657 	int count=0, unload=0;
2658 	HashTable *target_function_table = function_table;
2659 	int error_type;
2660 	zend_string *lowercase_name;
2661 	size_t fname_len;
2662 
2663 	if (type==MODULE_PERSISTENT) {
2664 		error_type = E_CORE_WARNING;
2665 	} else {
2666 		error_type = E_WARNING;
2667 	}
2668 
2669 	if (!target_function_table) {
2670 		target_function_table = CG(function_table);
2671 	}
2672 	internal_function->type = ZEND_INTERNAL_FUNCTION;
2673 	internal_function->module = EG(current_module);
2674 	memset(internal_function->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
2675 
2676 	while (ptr->fname) {
2677 		fname_len = strlen(ptr->fname);
2678 		internal_function->handler = ptr->handler;
2679 		internal_function->function_name = zend_string_init_interned(ptr->fname, fname_len, 1);
2680 		internal_function->scope = scope;
2681 		internal_function->prototype = NULL;
2682 		internal_function->attributes = NULL;
2683 		if (ptr->flags) {
2684 			if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
2685 				if (ptr->flags != ZEND_ACC_DEPRECATED && scope) {
2686 					zend_error(error_type, "Invalid access level for %s%s%s() - access must be exactly one of public, protected or private", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2687 				}
2688 				internal_function->fn_flags = ZEND_ACC_PUBLIC | ptr->flags;
2689 			} else {
2690 				internal_function->fn_flags = ptr->flags;
2691 			}
2692 		} else {
2693 			internal_function->fn_flags = ZEND_ACC_PUBLIC;
2694 		}
2695 
2696 		if (ptr->arg_info) {
2697 			zend_internal_function_info *info = (zend_internal_function_info*)ptr->arg_info;
2698 			internal_function->arg_info = (zend_internal_arg_info*)ptr->arg_info+1;
2699 			internal_function->num_args = ptr->num_args;
2700 			/* Currently you cannot denote that the function can accept less arguments than num_args */
2701 			if (info->required_num_args == (zend_uintptr_t)-1) {
2702 				internal_function->required_num_args = ptr->num_args;
2703 			} else {
2704 				internal_function->required_num_args = info->required_num_args;
2705 			}
2706 			if (ZEND_ARG_SEND_MODE(info)) {
2707 				internal_function->fn_flags |= ZEND_ACC_RETURN_REFERENCE;
2708 			}
2709 			if (ZEND_ARG_IS_VARIADIC(&ptr->arg_info[ptr->num_args])) {
2710 				internal_function->fn_flags |= ZEND_ACC_VARIADIC;
2711 				/* Don't count the variadic argument */
2712 				internal_function->num_args--;
2713 			}
2714 			if (ZEND_TYPE_IS_SET(info->type)) {
2715 				if (ZEND_TYPE_HAS_NAME(info->type)) {
2716 					const char *type_name = ZEND_TYPE_LITERAL_NAME(info->type);
2717 					if (!scope && (!strcasecmp(type_name, "self") || !strcasecmp(type_name, "parent"))) {
2718 						zend_error_noreturn(E_CORE_ERROR, "Cannot declare a return type of %s outside of a class scope", type_name);
2719 					}
2720 				}
2721 
2722 				internal_function->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
2723 			}
2724 		} else {
2725 			zend_error(E_CORE_WARNING, "Missing arginfo for %s%s%s()",
2726 				 scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2727 
2728 			internal_function->arg_info = NULL;
2729 			internal_function->num_args = 0;
2730 			internal_function->required_num_args = 0;
2731 		}
2732 
2733 		/* If not specified, add __toString() return type for compatibility with Stringable
2734 		 * interface. */
2735 		if (scope && zend_string_equals_literal_ci(internal_function->function_name, "__tostring") &&
2736 				!(internal_function->fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
2737 			internal_function->arg_info = (zend_internal_arg_info *) arg_info_toString + 1;
2738 			internal_function->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
2739 			internal_function->num_args = internal_function->required_num_args = 0;
2740 		}
2741 
2742 
2743 		zend_set_function_arg_flags((zend_function*)internal_function);
2744 		if (ptr->flags & ZEND_ACC_ABSTRACT) {
2745 			if (scope) {
2746 				/* This is a class that must be abstract itself. Here we set the check info. */
2747 				scope->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
2748 				if (!(scope->ce_flags & ZEND_ACC_INTERFACE)) {
2749 					/* Since the class is not an interface it needs to be declared as a abstract class. */
2750 					/* Since here we are handling internal functions only we can add the keyword flag. */
2751 					/* This time we set the flag for the keyword 'abstract'. */
2752 					scope->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
2753 				}
2754 			}
2755 			if ((ptr->flags & ZEND_ACC_STATIC) && (!scope || !(scope->ce_flags & ZEND_ACC_INTERFACE))) {
2756 				zend_error(error_type, "Static function %s%s%s() cannot be abstract", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2757 			}
2758 		} else {
2759 			if (scope && (scope->ce_flags & ZEND_ACC_INTERFACE)) {
2760 				zend_error(error_type, "Interface %s cannot contain non abstract method %s()", ZSTR_VAL(scope->name), ptr->fname);
2761 				return FAILURE;
2762 			}
2763 			if (!internal_function->handler) {
2764 				zend_error(error_type, "Method %s%s%s() cannot be a NULL function", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2765 				zend_unregister_functions(functions, count, target_function_table);
2766 				return FAILURE;
2767 			}
2768 		}
2769 		lowercase_name = zend_string_tolower_ex(internal_function->function_name, type == MODULE_PERSISTENT);
2770 		lowercase_name = zend_new_interned_string(lowercase_name);
2771 		reg_function = malloc(sizeof(zend_internal_function));
2772 		memcpy(reg_function, &function, sizeof(zend_internal_function));
2773 		if (zend_hash_add_ptr(target_function_table, lowercase_name, reg_function) == NULL) {
2774 			unload=1;
2775 			free(reg_function);
2776 			zend_string_release(lowercase_name);
2777 			break;
2778 		}
2779 
2780 		/* Get parameter count including variadic parameter. */
2781 		uint32_t num_args = reg_function->common.num_args;
2782 		if (reg_function->common.fn_flags & ZEND_ACC_VARIADIC) {
2783 			num_args++;
2784 		}
2785 
2786 		/* If types of arguments have to be checked */
2787 		if (reg_function->common.arg_info && num_args) {
2788 			uint32_t i;
2789 			for (i = 0; i < num_args; i++) {
2790 				zend_internal_arg_info *arg_info = &reg_function->internal_function.arg_info[i];
2791 				ZEND_ASSERT(arg_info->name && "Parameter must have a name");
2792 				if (ZEND_TYPE_IS_SET(arg_info->type)) {
2793 				    reg_function->common.fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
2794 				}
2795 #if ZEND_DEBUG
2796 				for (uint32_t j = 0; j < i; j++) {
2797 					if (!strcmp(arg_info->name, reg_function->internal_function.arg_info[j].name)) {
2798 						zend_error_noreturn(E_CORE_ERROR,
2799 							"Duplicate parameter name $%s for function %s%s%s()", arg_info->name,
2800 							scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2801 					}
2802 				}
2803 #endif
2804 			}
2805 		}
2806 
2807 		if (reg_function->common.arg_info &&
2808 		    (reg_function->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS))) {
2809 			/* convert "const char*" class type names into "zend_string*" */
2810 			uint32_t i;
2811 			zend_arg_info *arg_info = reg_function->common.arg_info - 1;
2812 			zend_arg_info *new_arg_info;
2813 
2814 			/* Treat return type as an extra argument */
2815 			num_args++;
2816 			new_arg_info = malloc(sizeof(zend_arg_info) * num_args);
2817 			memcpy(new_arg_info, arg_info, sizeof(zend_arg_info) * num_args);
2818 			reg_function->common.arg_info = new_arg_info + 1;
2819 			for (i = 0; i < num_args; i++) {
2820 				if (ZEND_TYPE_IS_COMPLEX(new_arg_info[i].type)) {
2821 					ZEND_ASSERT(ZEND_TYPE_HAS_NAME(new_arg_info[i].type)
2822 						&& "Should be stored as simple name");
2823 					const char *class_name = ZEND_TYPE_LITERAL_NAME(new_arg_info[i].type);
2824 
2825 					size_t num_types = 1;
2826 					const char *p = class_name;
2827 					while ((p = strchr(p, '|'))) {
2828 						num_types++;
2829 						p++;
2830 					}
2831 
2832 					if (num_types == 1) {
2833 						/* Simple class type */
2834 						ZEND_TYPE_SET_PTR(new_arg_info[i].type,
2835 							zend_string_init_interned(class_name, strlen(class_name), 1));
2836 					} else {
2837 						/* Union type */
2838 						zend_type_list *list = malloc(ZEND_TYPE_LIST_SIZE(num_types));
2839 						list->num_types = num_types;
2840 						ZEND_TYPE_SET_LIST(new_arg_info[i].type, list);
2841 						ZEND_TYPE_FULL_MASK(new_arg_info[i].type) |= _ZEND_TYPE_UNION_BIT;
2842 
2843 						const char *start = class_name;
2844 						uint32_t j = 0;
2845 						while (true) {
2846 							const char *end = strchr(start, '|');
2847 							zend_string *str = zend_string_init_interned(
2848 								start, end ? end - start : strlen(start), 1);
2849 							list->types[j] = (zend_type) ZEND_TYPE_INIT_CLASS(str, 0, 0);
2850 							if (!end) {
2851 								break;
2852 							}
2853 							start = end + 1;
2854 							j++;
2855 						}
2856 					}
2857 				}
2858 			}
2859 		}
2860 
2861 		if (scope) {
2862 			zend_check_magic_method_implementation(
2863 				scope, reg_function, lowercase_name, E_CORE_ERROR);
2864 			zend_add_magic_method(scope, reg_function, lowercase_name);
2865 		}
2866 		ptr++;
2867 		count++;
2868 		zend_string_release(lowercase_name);
2869 	}
2870 	if (unload) { /* before unloading, display all remaining bad function in the module */
2871 		while (ptr->fname) {
2872 			fname_len = strlen(ptr->fname);
2873 			lowercase_name = zend_string_alloc(fname_len, 0);
2874 			zend_str_tolower_copy(ZSTR_VAL(lowercase_name), ptr->fname, fname_len);
2875 			if (zend_hash_exists(target_function_table, lowercase_name)) {
2876 				zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2877 			}
2878 			zend_string_efree(lowercase_name);
2879 			ptr++;
2880 		}
2881 		zend_unregister_functions(functions, count, target_function_table);
2882 		return FAILURE;
2883 	}
2884 	return SUCCESS;
2885 }
2886 /* }}} */
2887 
2888 /* count=-1 means erase all functions, otherwise,
2889  * erase the first count functions
2890  */
zend_unregister_functions(const zend_function_entry * functions,int count,HashTable * function_table)2891 ZEND_API void zend_unregister_functions(const zend_function_entry *functions, int count, HashTable *function_table) /* {{{ */
2892 {
2893 	const zend_function_entry *ptr = functions;
2894 	int i=0;
2895 	HashTable *target_function_table = function_table;
2896 	zend_string *lowercase_name;
2897 	size_t fname_len;
2898 
2899 	if (!target_function_table) {
2900 		target_function_table = CG(function_table);
2901 	}
2902 	while (ptr->fname) {
2903 		if (count!=-1 && i>=count) {
2904 			break;
2905 		}
2906 		fname_len = strlen(ptr->fname);
2907 		lowercase_name = zend_string_alloc(fname_len, 0);
2908 		zend_str_tolower_copy(ZSTR_VAL(lowercase_name), ptr->fname, fname_len);
2909 		zend_hash_del(target_function_table, lowercase_name);
2910 		zend_string_efree(lowercase_name);
2911 		ptr++;
2912 		i++;
2913 	}
2914 }
2915 /* }}} */
2916 
zend_startup_module(zend_module_entry * module)2917 ZEND_API zend_result zend_startup_module(zend_module_entry *module) /* {{{ */
2918 {
2919 	if ((module = zend_register_internal_module(module)) != NULL && zend_startup_module_ex(module) == SUCCESS) {
2920 		return SUCCESS;
2921 	}
2922 	return FAILURE;
2923 }
2924 /* }}} */
2925 
zend_get_module_started(const char * module_name)2926 ZEND_API zend_result zend_get_module_started(const char *module_name) /* {{{ */
2927 {
2928 	zend_module_entry *module;
2929 
2930 	module = zend_hash_str_find_ptr(&module_registry, module_name, strlen(module_name));
2931 	return (module && module->module_started) ? SUCCESS : FAILURE;
2932 }
2933 /* }}} */
2934 
clean_module_class(zval * el,void * arg)2935 static int clean_module_class(zval *el, void *arg) /* {{{ */
2936 {
2937 	zend_class_entry *ce = (zend_class_entry *)Z_PTR_P(el);
2938 	int module_number = *(int *)arg;
2939 	if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module->module_number == module_number) {
2940 		return ZEND_HASH_APPLY_REMOVE;
2941 	} else {
2942 		return ZEND_HASH_APPLY_KEEP;
2943 	}
2944 }
2945 /* }}} */
2946 
clean_module_classes(int module_number)2947 static void clean_module_classes(int module_number) /* {{{ */
2948 {
2949 	zend_hash_apply_with_argument(EG(class_table), clean_module_class, (void *) &module_number);
2950 }
2951 /* }}} */
2952 
module_destructor(zend_module_entry * module)2953 void module_destructor(zend_module_entry *module) /* {{{ */
2954 {
2955 #if ZEND_RC_DEBUG
2956 	bool orig_rc_debug = zend_rc_debug;
2957 #endif
2958 
2959 	if (module->type == MODULE_TEMPORARY) {
2960 #if ZEND_RC_DEBUG
2961 		/* FIXME: Loading extensions during the request breaks some invariants.
2962 		 * In particular, it will create persistent interned strings, which is
2963 		 * not allowed at this stage. */
2964 		zend_rc_debug = false;
2965 #endif
2966 		zend_clean_module_rsrc_dtors(module->module_number);
2967 		clean_module_constants(module->module_number);
2968 		clean_module_classes(module->module_number);
2969 	}
2970 
2971 	if (module->module_started && module->module_shutdown_func) {
2972 #if 0
2973 		zend_printf("%s: Module shutdown\n", module->name);
2974 #endif
2975 		module->module_shutdown_func(module->type, module->module_number);
2976 	}
2977 
2978 	if (module->module_started
2979 	 && !module->module_shutdown_func
2980 	 && module->type == MODULE_TEMPORARY) {
2981 		zend_unregister_ini_entries_ex(module->module_number, module->type);
2982 	}
2983 
2984 	/* Deinitialize module globals */
2985 	if (module->globals_size) {
2986 #ifdef ZTS
2987 		if (*module->globals_id_ptr) {
2988 			ts_free_id(*module->globals_id_ptr);
2989 		}
2990 #else
2991 		if (module->globals_dtor) {
2992 			module->globals_dtor(module->globals_ptr);
2993 		}
2994 #endif
2995 	}
2996 
2997 	module->module_started=0;
2998 	if (module->type == MODULE_TEMPORARY && module->functions) {
2999 		zend_unregister_functions(module->functions, -1, NULL);
3000 	}
3001 
3002 #if HAVE_LIBDL
3003 	if (module->handle && !getenv("ZEND_DONT_UNLOAD_MODULES")) {
3004 		DL_UNLOAD(module->handle);
3005 	}
3006 #endif
3007 
3008 #if ZEND_RC_DEBUG
3009 	zend_rc_debug = orig_rc_debug;
3010 #endif
3011 }
3012 /* }}} */
3013 
zend_activate_modules(void)3014 ZEND_API void zend_activate_modules(void) /* {{{ */
3015 {
3016 	zend_module_entry **p = module_request_startup_handlers;
3017 
3018 	while (*p) {
3019 		zend_module_entry *module = *p;
3020 
3021 		if (module->request_startup_func(module->type, module->module_number)==FAILURE) {
3022 			zend_error(E_WARNING, "request_startup() for %s module failed", module->name);
3023 			exit(1);
3024 		}
3025 		p++;
3026 	}
3027 }
3028 /* }}} */
3029 
zend_deactivate_modules(void)3030 ZEND_API void zend_deactivate_modules(void) /* {{{ */
3031 {
3032 	EG(current_execute_data) = NULL; /* we're no longer executing anything */
3033 
3034 	if (EG(full_tables_cleanup)) {
3035 		zend_module_entry *module;
3036 
3037 		ZEND_HASH_REVERSE_FOREACH_PTR(&module_registry, module) {
3038 			if (module->request_shutdown_func) {
3039 				zend_try {
3040 					module->request_shutdown_func(module->type, module->module_number);
3041 				} zend_end_try();
3042 			}
3043 		} ZEND_HASH_FOREACH_END();
3044 	} else {
3045 		zend_module_entry **p = module_request_shutdown_handlers;
3046 
3047 		while (*p) {
3048 			zend_module_entry *module = *p;
3049 			zend_try {
3050 				module->request_shutdown_func(module->type, module->module_number);
3051 			} zend_end_try();
3052 			p++;
3053 		}
3054 	}
3055 }
3056 /* }}} */
3057 
zend_post_deactivate_modules(void)3058 ZEND_API void zend_post_deactivate_modules(void) /* {{{ */
3059 {
3060 	if (EG(full_tables_cleanup)) {
3061 		zend_module_entry *module;
3062 		zval *zv;
3063 		zend_string *key;
3064 
3065 		ZEND_HASH_FOREACH_PTR(&module_registry, module) {
3066 			if (module->post_deactivate_func) {
3067 				module->post_deactivate_func();
3068 			}
3069 		} ZEND_HASH_FOREACH_END();
3070 		ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(&module_registry, key, zv) {
3071 			module = Z_PTR_P(zv);
3072 			if (module->type != MODULE_TEMPORARY) {
3073 				break;
3074 			}
3075 			module_destructor(module);
3076 			free(module);
3077 			zend_string_release_ex(key, 0);
3078 		} ZEND_HASH_FOREACH_END_DEL();
3079 	} else {
3080 		zend_module_entry **p = module_post_deactivate_handlers;
3081 
3082 		while (*p) {
3083 			zend_module_entry *module = *p;
3084 
3085 			module->post_deactivate_func();
3086 			p++;
3087 		}
3088 	}
3089 }
3090 /* }}} */
3091 
3092 /* return the next free module number */
zend_next_free_module(void)3093 ZEND_API int zend_next_free_module(void) /* {{{ */
3094 {
3095 	return zend_hash_num_elements(&module_registry) + 1;
3096 }
3097 /* }}} */
3098 
do_register_internal_class(zend_class_entry * orig_class_entry,uint32_t ce_flags)3099 static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, uint32_t ce_flags) /* {{{ */
3100 {
3101 	zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
3102 	zend_string *lowercase_name;
3103 	*class_entry = *orig_class_entry;
3104 
3105 	class_entry->type = ZEND_INTERNAL_CLASS;
3106 	zend_initialize_class_data(class_entry, 0);
3107 	zend_alloc_ce_cache(class_entry->name);
3108 	class_entry->ce_flags = orig_class_entry->ce_flags | ce_flags | ZEND_ACC_CONSTANTS_UPDATED | ZEND_ACC_LINKED | ZEND_ACC_RESOLVED_PARENT | ZEND_ACC_RESOLVED_INTERFACES;
3109 	class_entry->info.internal.module = EG(current_module);
3110 
3111 	if (class_entry->info.internal.builtin_functions) {
3112 		zend_register_functions(class_entry, class_entry->info.internal.builtin_functions, &class_entry->function_table, EG(current_module)->type);
3113 	}
3114 
3115 	lowercase_name = zend_string_tolower_ex(orig_class_entry->name, EG(current_module)->type == MODULE_PERSISTENT);
3116 	lowercase_name = zend_new_interned_string(lowercase_name);
3117 	zend_hash_update_ptr(CG(class_table), lowercase_name, class_entry);
3118 	zend_string_release_ex(lowercase_name, 1);
3119 
3120 	if (class_entry->__tostring && !zend_string_equals_literal(class_entry->name, "Stringable")
3121 			&& !(class_entry->ce_flags & ZEND_ACC_TRAIT)) {
3122 		ZEND_ASSERT(zend_ce_stringable
3123 			&& "Should be registered before first class using __toString()");
3124 		zend_do_implement_interface(class_entry, zend_ce_stringable);
3125 	}
3126 	return class_entry;
3127 }
3128 /* }}} */
3129 
3130 /* If parent_ce is not NULL then it inherits from parent_ce
3131  * If parent_ce is NULL and parent_name isn't then it looks for the parent and inherits from it
3132  * If both parent_ce and parent_name are NULL it does a regular class registration
3133  * If parent_name is specified but not found NULL is returned
3134  */
zend_register_internal_class_ex(zend_class_entry * class_entry,zend_class_entry * parent_ce)3135 ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce) /* {{{ */
3136 {
3137 	zend_class_entry *register_class;
3138 
3139 	register_class = zend_register_internal_class(class_entry);
3140 
3141 	if (parent_ce) {
3142 		zend_do_inheritance(register_class, parent_ce);
3143 		zend_build_properties_info_table(register_class);
3144 	}
3145 
3146 	return register_class;
3147 }
3148 /* }}} */
3149 
zend_class_implements(zend_class_entry * class_entry,int num_interfaces,...)3150 ZEND_API void zend_class_implements(zend_class_entry *class_entry, int num_interfaces, ...) /* {{{ */
3151 {
3152 	zend_class_entry *interface_entry;
3153 	va_list interface_list;
3154 	va_start(interface_list, num_interfaces);
3155 
3156 	while (num_interfaces--) {
3157 		interface_entry = va_arg(interface_list, zend_class_entry *);
3158 		if (interface_entry == zend_ce_stringable
3159 				&& zend_class_implements_interface(class_entry, zend_ce_stringable)) {
3160 			/* Stringable is implemented automatically,
3161 			 * silently ignore an explicit implementation. */
3162 			continue;
3163 		}
3164 
3165 		zend_do_implement_interface(class_entry, interface_entry);
3166 	}
3167 
3168 	va_end(interface_list);
3169 }
3170 /* }}} */
3171 
3172 /* A class that contains at least one abstract method automatically becomes an abstract class.
3173  */
zend_register_internal_class(zend_class_entry * orig_class_entry)3174 ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry) /* {{{ */
3175 {
3176 	return do_register_internal_class(orig_class_entry, 0);
3177 }
3178 /* }}} */
3179 
zend_register_internal_interface(zend_class_entry * orig_class_entry)3180 ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry) /* {{{ */
3181 {
3182 	return do_register_internal_class(orig_class_entry, ZEND_ACC_INTERFACE);
3183 }
3184 /* }}} */
3185 
zend_register_class_alias_ex(const char * name,size_t name_len,zend_class_entry * ce,bool persistent)3186 ZEND_API zend_result zend_register_class_alias_ex(const char *name, size_t name_len, zend_class_entry *ce, bool persistent) /* {{{ */
3187 {
3188 	zend_string *lcname;
3189 	zval zv, *ret;
3190 
3191 	/* TODO: Move this out of here in 7.4. */
3192 	if (persistent && EG(current_module) && EG(current_module)->type == MODULE_TEMPORARY) {
3193 		persistent = 0;
3194 	}
3195 
3196 	if (name[0] == '\\') {
3197 		lcname = zend_string_alloc(name_len-1, persistent);
3198 		zend_str_tolower_copy(ZSTR_VAL(lcname), name+1, name_len-1);
3199 	} else {
3200 		lcname = zend_string_alloc(name_len, persistent);
3201 		zend_str_tolower_copy(ZSTR_VAL(lcname), name, name_len);
3202 	}
3203 
3204 	zend_assert_valid_class_name(lcname);
3205 
3206 	lcname = zend_new_interned_string(lcname);
3207 
3208 	ZVAL_ALIAS_PTR(&zv, ce);
3209 	ret = zend_hash_add(CG(class_table), lcname, &zv);
3210 	zend_string_release_ex(lcname, 0);
3211 	if (ret) {
3212 		if (!(ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
3213 			ce->refcount++;
3214 		}
3215 		return SUCCESS;
3216 	}
3217 	return FAILURE;
3218 }
3219 /* }}} */
3220 
3221 // TODO num_symbol_tables as unsigned int?
zend_set_hash_symbol(zval * symbol,const char * name,size_t name_length,bool is_ref,int num_symbol_tables,...)3222 ZEND_API zend_result zend_set_hash_symbol(zval *symbol, const char *name, size_t name_length, bool is_ref, int num_symbol_tables, ...) /* {{{ */
3223 {
3224 	HashTable *symbol_table;
3225 	va_list symbol_table_list;
3226 
3227 	if (num_symbol_tables <= 0) return FAILURE;
3228 
3229 	if (is_ref) {
3230 		ZVAL_MAKE_REF(symbol);
3231 	}
3232 
3233 	va_start(symbol_table_list, num_symbol_tables);
3234 	while (num_symbol_tables-- > 0) {
3235 		symbol_table = va_arg(symbol_table_list, HashTable *);
3236 		zend_hash_str_update(symbol_table, name, name_length, symbol);
3237 		Z_TRY_ADDREF_P(symbol);
3238 	}
3239 	va_end(symbol_table_list);
3240 	return SUCCESS;
3241 }
3242 /* }}} */
3243 
3244 /* Disabled functions support */
3245 
zend_disable_function(const char * function_name,size_t function_name_length)3246 static void zend_disable_function(const char *function_name, size_t function_name_length)
3247 {
3248 	zend_hash_str_del(CG(function_table), function_name, function_name_length);
3249 }
3250 
zend_disable_functions(const char * function_list)3251 ZEND_API void zend_disable_functions(const char *function_list) /* {{{ */
3252 {
3253 	if (!function_list || !*function_list) {
3254 		return;
3255 	}
3256 
3257 	const char *s = NULL, *e = function_list;
3258 	while (*e) {
3259 		switch (*e) {
3260 			case ' ':
3261 			case ',':
3262 				if (s) {
3263 					zend_disable_function(s, e - s);
3264 					s = NULL;
3265 				}
3266 				break;
3267 			default:
3268 				if (!s) {
3269 					s = e;
3270 				}
3271 				break;
3272 		}
3273 		e++;
3274 	}
3275 	if (s) {
3276 		zend_disable_function(s, e - s);
3277 	}
3278 
3279 	/* Rehash the function table after deleting functions. This ensures that all internal
3280 	 * functions are contiguous, which means we don't need to perform full table cleanup
3281 	 * on shutdown. */
3282 	zend_hash_rehash(CG(function_table));
3283 }
3284 /* }}} */
3285 
3286 #ifdef ZEND_WIN32
3287 #pragma optimize("", off)
3288 #endif
display_disabled_class(zend_class_entry * class_type)3289 static ZEND_COLD zend_object *display_disabled_class(zend_class_entry *class_type) /* {{{ */
3290 {
3291 	zend_object *intern;
3292 
3293 	intern = zend_objects_new(class_type);
3294 
3295 	/* Initialize default properties */
3296 	if (EXPECTED(class_type->default_properties_count != 0)) {
3297 		zval *p = intern->properties_table;
3298 		zval *end = p + class_type->default_properties_count;
3299 		do {
3300 			ZVAL_UNDEF(p);
3301 			p++;
3302 		} while (p != end);
3303 	}
3304 
3305 	zend_error(E_WARNING, "%s() has been disabled for security reasons", ZSTR_VAL(class_type->name));
3306 	return intern;
3307 }
3308 #ifdef ZEND_WIN32
3309 #pragma optimize("", on)
3310 #endif
3311 /* }}} */
3312 
3313 static const zend_function_entry disabled_class_new[] = {
3314 	ZEND_FE_END
3315 };
3316 
zend_disable_class(const char * class_name,size_t class_name_length)3317 ZEND_API zend_result zend_disable_class(const char *class_name, size_t class_name_length) /* {{{ */
3318 {
3319 	zend_class_entry *disabled_class;
3320 	zend_string *key;
3321 	zend_function *fn;
3322 	zend_property_info *prop;
3323 
3324 	key = zend_string_alloc(class_name_length, 0);
3325 	zend_str_tolower_copy(ZSTR_VAL(key), class_name, class_name_length);
3326 	disabled_class = zend_hash_find_ptr(CG(class_table), key);
3327 	zend_string_release_ex(key, 0);
3328 	if (!disabled_class) {
3329 		return FAILURE;
3330 	}
3331 
3332 	/* Will be reset by INIT_CLASS_ENTRY. */
3333 	free(disabled_class->interfaces);
3334 
3335 	INIT_CLASS_ENTRY_INIT_METHODS((*disabled_class), disabled_class_new);
3336 	disabled_class->create_object = display_disabled_class;
3337 
3338 	ZEND_HASH_FOREACH_PTR(&disabled_class->function_table, fn) {
3339 		if ((fn->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) &&
3340 			fn->common.scope == disabled_class) {
3341 			zend_free_internal_arg_info(&fn->internal_function);
3342 		}
3343 	} ZEND_HASH_FOREACH_END();
3344 	zend_hash_clean(&disabled_class->function_table);
3345 	ZEND_HASH_FOREACH_PTR(&disabled_class->properties_info, prop) {
3346 		if (prop->ce == disabled_class) {
3347 			zend_string_release(prop->name);
3348 			zend_type_release(prop->type, /* persistent */ 1);
3349 			free(prop);
3350 		}
3351 	} ZEND_HASH_FOREACH_END();
3352 	zend_hash_clean(&disabled_class->properties_info);
3353 	return SUCCESS;
3354 }
3355 /* }}} */
3356 
get_scope(zend_execute_data * frame)3357 static zend_always_inline zend_class_entry *get_scope(zend_execute_data *frame)
3358 {
3359 	return frame && frame->func ? frame->func->common.scope : NULL;
3360 }
3361 
zend_is_callable_check_class(zend_string * name,zend_class_entry * scope,zend_execute_data * frame,zend_fcall_info_cache * fcc,bool * strict_class,char ** error)3362 static bool zend_is_callable_check_class(zend_string *name, zend_class_entry *scope, zend_execute_data *frame, zend_fcall_info_cache *fcc, bool *strict_class, char **error) /* {{{ */
3363 {
3364 	bool ret = 0;
3365 	zend_class_entry *ce;
3366 	size_t name_len = ZSTR_LEN(name);
3367 	zend_string *lcname;
3368 	ALLOCA_FLAG(use_heap);
3369 
3370 	ZSTR_ALLOCA_ALLOC(lcname, name_len, use_heap);
3371 	zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(name), name_len);
3372 
3373 	*strict_class = 0;
3374 	if (zend_string_equals_literal(lcname, "self")) {
3375 		if (!scope) {
3376 			if (error) *error = estrdup("cannot access \"self\" when no class scope is active");
3377 		} else {
3378 			fcc->called_scope = zend_get_called_scope(frame);
3379 			if (!fcc->called_scope || !instanceof_function(fcc->called_scope, scope)) {
3380 				fcc->called_scope = scope;
3381 			}
3382 			fcc->calling_scope = scope;
3383 			if (!fcc->object) {
3384 				fcc->object = zend_get_this_object(frame);
3385 			}
3386 			ret = 1;
3387 		}
3388 	} else if (zend_string_equals_literal(lcname, "parent")) {
3389 		if (!scope) {
3390 			if (error) *error = estrdup("cannot access \"parent\" when no class scope is active");
3391 		} else if (!scope->parent) {
3392 			if (error) *error = estrdup("cannot access \"parent\" when current class scope has no parent");
3393 		} else {
3394 			fcc->called_scope = zend_get_called_scope(frame);
3395 			if (!fcc->called_scope || !instanceof_function(fcc->called_scope, scope->parent)) {
3396 				fcc->called_scope = scope->parent;
3397 			}
3398 			fcc->calling_scope = scope->parent;
3399 			if (!fcc->object) {
3400 				fcc->object = zend_get_this_object(frame);
3401 			}
3402 			*strict_class = 1;
3403 			ret = 1;
3404 		}
3405 	} else if (zend_string_equals_literal(lcname, "static")) {
3406 		zend_class_entry *called_scope = zend_get_called_scope(frame);
3407 
3408 		if (!called_scope) {
3409 			if (error) *error = estrdup("cannot access \"static\" when no class scope is active");
3410 		} else {
3411 			fcc->called_scope = called_scope;
3412 			fcc->calling_scope = called_scope;
3413 			if (!fcc->object) {
3414 				fcc->object = zend_get_this_object(frame);
3415 			}
3416 			*strict_class = 1;
3417 			ret = 1;
3418 		}
3419 	} else if ((ce = zend_lookup_class(name)) != NULL) {
3420 		zend_class_entry *scope = get_scope(frame);
3421 		fcc->calling_scope = ce;
3422 		if (scope && !fcc->object) {
3423 			zend_object *object = zend_get_this_object(frame);
3424 
3425 			if (object &&
3426 			    instanceof_function(object->ce, scope) &&
3427 			    instanceof_function(scope, ce)) {
3428 				fcc->object = object;
3429 				fcc->called_scope = object->ce;
3430 			} else {
3431 				fcc->called_scope = ce;
3432 			}
3433 		} else {
3434 			fcc->called_scope = fcc->object ? fcc->object->ce : ce;
3435 		}
3436 		*strict_class = 1;
3437 		ret = 1;
3438 	} else {
3439 		if (error) zend_spprintf(error, 0, "class \"%.*s\" not found", (int)name_len, ZSTR_VAL(name));
3440 	}
3441 	ZSTR_ALLOCA_FREE(lcname, use_heap);
3442 	return ret;
3443 }
3444 /* }}} */
3445 
zend_release_fcall_info_cache(zend_fcall_info_cache * fcc)3446 ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc) {
3447 	if (fcc->function_handler &&
3448 		(fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
3449 		if (fcc->function_handler->common.function_name) {
3450 			zend_string_release_ex(fcc->function_handler->common.function_name, 0);
3451 		}
3452 		zend_free_trampoline(fcc->function_handler);
3453 		fcc->function_handler = NULL;
3454 	}
3455 }
3456 
zend_is_callable_check_func(int check_flags,zval * callable,zend_execute_data * frame,zend_fcall_info_cache * fcc,bool strict_class,char ** error)3457 static zend_always_inline bool zend_is_callable_check_func(int check_flags, zval *callable, zend_execute_data *frame, zend_fcall_info_cache *fcc, bool strict_class, char **error) /* {{{ */
3458 {
3459 	zend_class_entry *ce_org = fcc->calling_scope;
3460 	bool retval = 0;
3461 	zend_string *mname, *cname;
3462 	zend_string *lmname;
3463 	const char *colon;
3464 	size_t clen;
3465 	HashTable *ftable;
3466 	int call_via_handler = 0;
3467 	zend_class_entry *scope;
3468 	zval *zv;
3469 	ALLOCA_FLAG(use_heap)
3470 
3471 	fcc->calling_scope = NULL;
3472 
3473 	if (!ce_org) {
3474 		zend_function *func;
3475 		zend_string *lmname;
3476 
3477 		/* Check if function with given name exists.
3478 		 * This may be a compound name that includes namespace name */
3479 		if (UNEXPECTED(Z_STRVAL_P(callable)[0] == '\\')) {
3480 			/* Skip leading \ */
3481 			ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable) - 1, use_heap);
3482 			zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable) + 1, Z_STRLEN_P(callable) - 1);
3483 			func = zend_fetch_function(lmname);
3484 			ZSTR_ALLOCA_FREE(lmname, use_heap);
3485 		} else {
3486 			lmname = Z_STR_P(callable);
3487 			func = zend_fetch_function(lmname);
3488 			if (!func) {
3489 				ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable), use_heap);
3490 				zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable), Z_STRLEN_P(callable));
3491 				func = zend_fetch_function(lmname);
3492 				ZSTR_ALLOCA_FREE(lmname, use_heap);
3493 			}
3494 		}
3495 		if (EXPECTED(func != NULL)) {
3496 			fcc->function_handler = func;
3497 			return 1;
3498 		}
3499 	}
3500 
3501 	/* Split name into class/namespace and method/function names */
3502 	if ((colon = zend_memrchr(Z_STRVAL_P(callable), ':', Z_STRLEN_P(callable))) != NULL &&
3503 		colon > Z_STRVAL_P(callable) &&
3504 		*(colon-1) == ':'
3505 	) {
3506 		size_t mlen;
3507 
3508 		colon--;
3509 		clen = colon - Z_STRVAL_P(callable);
3510 		mlen = Z_STRLEN_P(callable) - clen - 2;
3511 
3512 		if (colon == Z_STRVAL_P(callable)) {
3513 			if (error) *error = estrdup("invalid function name");
3514 			return 0;
3515 		}
3516 
3517 		/* This is a compound name.
3518 		 * Try to fetch class and then find static method. */
3519 		if (ce_org) {
3520 			scope = ce_org;
3521 		} else {
3522 			scope = get_scope(frame);
3523 		}
3524 
3525 		cname = zend_string_init_interned(Z_STRVAL_P(callable), clen, 0);
3526 		if (ZSTR_HAS_CE_CACHE(cname) && ZSTR_GET_CE_CACHE(cname)) {
3527 			fcc->calling_scope = ZSTR_GET_CE_CACHE(cname);
3528 			if (scope && !fcc->object) {
3529 				zend_object *object = zend_get_this_object(frame);
3530 
3531 				if (object &&
3532 				    instanceof_function(object->ce, scope) &&
3533 				    instanceof_function(scope, fcc->calling_scope)) {
3534 					fcc->object = object;
3535 					fcc->called_scope = object->ce;
3536 				} else {
3537 					fcc->called_scope = fcc->calling_scope;
3538 				}
3539 			} else {
3540 				fcc->called_scope = fcc->object ? fcc->object->ce : fcc->calling_scope;
3541 			}
3542 			strict_class = 1;
3543 		} else if (!zend_is_callable_check_class(cname, scope, frame, fcc, &strict_class, error)) {
3544 			zend_string_release_ex(cname, 0);
3545 			return 0;
3546 		}
3547 		zend_string_release_ex(cname, 0);
3548 
3549 		ftable = &fcc->calling_scope->function_table;
3550 		if (ce_org && !instanceof_function(ce_org, fcc->calling_scope)) {
3551 			if (error) zend_spprintf(error, 0, "class %s is not a subclass of %s", ZSTR_VAL(ce_org->name), ZSTR_VAL(fcc->calling_scope->name));
3552 			return 0;
3553 		}
3554 		mname = zend_string_init(Z_STRVAL_P(callable) + clen + 2, mlen, 0);
3555 	} else if (ce_org) {
3556 		/* Try to fetch find static method of given class. */
3557 		mname = Z_STR_P(callable);
3558 		zend_string_addref(mname);
3559 		ftable = &ce_org->function_table;
3560 		fcc->calling_scope = ce_org;
3561 	} else {
3562 		/* We already checked for plain function before. */
3563 		if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) {
3564 			zend_spprintf(error, 0, "function \"%s\" not found or invalid function name", Z_STRVAL_P(callable));
3565 		}
3566 		return 0;
3567 	}
3568 
3569 	lmname = zend_string_tolower(mname);
3570 	if (strict_class &&
3571 	    fcc->calling_scope &&
3572 		zend_string_equals_literal(lmname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
3573 		fcc->function_handler = fcc->calling_scope->constructor;
3574 		if (fcc->function_handler) {
3575 			retval = 1;
3576 		}
3577 	} else if ((zv = zend_hash_find(ftable, lmname)) != NULL) {
3578 		fcc->function_handler = Z_PTR_P(zv);
3579 		retval = 1;
3580 		if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) &&
3581 		    !strict_class) {
3582 			scope = get_scope(frame);
3583 			if (scope &&
3584 			    instanceof_function(fcc->function_handler->common.scope, scope)) {
3585 
3586 				zv = zend_hash_find(&scope->function_table, lmname);
3587 				if (zv != NULL) {
3588 					zend_function *priv_fbc = Z_PTR_P(zv);
3589 
3590 					if ((priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE)
3591 					 && priv_fbc->common.scope == scope) {
3592 						fcc->function_handler = priv_fbc;
3593 					}
3594 				}
3595 			}
3596 		}
3597 		if (!(fcc->function_handler->common.fn_flags & ZEND_ACC_PUBLIC) &&
3598 		    (fcc->calling_scope &&
3599 		     ((fcc->object && fcc->calling_scope->__call) ||
3600 		      (!fcc->object && fcc->calling_scope->__callstatic)))) {
3601 			scope = get_scope(frame);
3602 			if (fcc->function_handler->common.scope != scope) {
3603 				if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PRIVATE)
3604 				 || !zend_check_protected(zend_get_function_root_class(fcc->function_handler), scope)) {
3605 					retval = 0;
3606 					fcc->function_handler = NULL;
3607 					goto get_function_via_handler;
3608 				}
3609 			}
3610 		}
3611 	} else {
3612 get_function_via_handler:
3613 		if (fcc->object && fcc->calling_scope == ce_org) {
3614 			if (strict_class && ce_org->__call) {
3615 				fcc->function_handler = zend_get_call_trampoline_func(ce_org, mname, 0);
3616 				call_via_handler = 1;
3617 				retval = 1;
3618 			} else {
3619 				fcc->function_handler = fcc->object->handlers->get_method(&fcc->object, mname, NULL);
3620 				if (fcc->function_handler) {
3621 					if (strict_class &&
3622 					    (!fcc->function_handler->common.scope ||
3623 					     !instanceof_function(ce_org, fcc->function_handler->common.scope))) {
3624 						zend_release_fcall_info_cache(fcc);
3625 					} else {
3626 						retval = 1;
3627 						call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
3628 					}
3629 				}
3630 			}
3631 		} else if (fcc->calling_scope) {
3632 			if (fcc->calling_scope->get_static_method) {
3633 				fcc->function_handler = fcc->calling_scope->get_static_method(fcc->calling_scope, mname);
3634 			} else {
3635 				fcc->function_handler = zend_std_get_static_method(fcc->calling_scope, mname, NULL);
3636 			}
3637 			if (fcc->function_handler) {
3638 				retval = 1;
3639 				call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
3640 				if (call_via_handler && !fcc->object) {
3641 					zend_object *object = zend_get_this_object(frame);
3642 					if (object &&
3643 					    instanceof_function(object->ce, fcc->calling_scope)) {
3644 						fcc->object = object;
3645 					}
3646 				}
3647 			}
3648 		}
3649 	}
3650 
3651 	if (retval) {
3652 		if (fcc->calling_scope && !call_via_handler) {
3653 			if (fcc->function_handler->common.fn_flags & ZEND_ACC_ABSTRACT) {
3654 				retval = 0;
3655 				if (error) {
3656 					zend_spprintf(error, 0, "cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
3657 				}
3658 			} else if (!fcc->object && !(fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) {
3659 				retval = 0;
3660 				if (error) {
3661 					zend_spprintf(error, 0, "non-static method %s::%s() cannot be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
3662 				}
3663 			}
3664 			if (retval
3665 			 && !(fcc->function_handler->common.fn_flags & ZEND_ACC_PUBLIC)) {
3666 				scope = get_scope(frame);
3667 				if (fcc->function_handler->common.scope != scope) {
3668 					if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PRIVATE)
3669 					 || (!zend_check_protected(zend_get_function_root_class(fcc->function_handler), scope))) {
3670 						if (error) {
3671 							if (*error) {
3672 								efree(*error);
3673 							}
3674 							zend_spprintf(error, 0, "cannot access %s method %s::%s()", zend_visibility_string(fcc->function_handler->common.fn_flags), ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
3675 						}
3676 						retval = 0;
3677 					}
3678 				}
3679 			}
3680 		}
3681 	} else if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) {
3682 		if (fcc->calling_scope) {
3683 			if (error) zend_spprintf(error, 0, "class %s does not have a method \"%s\"", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(mname));
3684 		} else {
3685 			if (error) zend_spprintf(error, 0, "function %s() does not exist", ZSTR_VAL(mname));
3686 		}
3687 	}
3688 	zend_string_release_ex(lmname, 0);
3689 	zend_string_release_ex(mname, 0);
3690 
3691 	if (fcc->object) {
3692 		fcc->called_scope = fcc->object->ce;
3693 		if (fcc->function_handler
3694 		 && (fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) {
3695 			fcc->object = NULL;
3696 		}
3697 	}
3698 	return retval;
3699 }
3700 /* }}} */
3701 
zend_get_callable_name_ex(zval * callable,zend_object * object)3702 ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *object) /* {{{ */
3703 {
3704 try_again:
3705 	switch (Z_TYPE_P(callable)) {
3706 		case IS_STRING:
3707 			if (object) {
3708 				return zend_create_member_string(object->ce->name, Z_STR_P(callable));
3709 			}
3710 			return zend_string_copy(Z_STR_P(callable));
3711 
3712 		case IS_ARRAY:
3713 		{
3714 			zval *method = NULL;
3715 			zval *obj = NULL;
3716 
3717 			if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
3718 				obj = zend_hash_index_find_deref(Z_ARRVAL_P(callable), 0);
3719 				method = zend_hash_index_find_deref(Z_ARRVAL_P(callable), 1);
3720 			}
3721 
3722 			if (obj == NULL || method == NULL || Z_TYPE_P(method) != IS_STRING) {
3723 				return ZSTR_KNOWN(ZEND_STR_ARRAY_CAPITALIZED);
3724 			}
3725 
3726 			if (Z_TYPE_P(obj) == IS_STRING) {
3727 				return zend_create_member_string(Z_STR_P(obj), Z_STR_P(method));
3728 			} else if (Z_TYPE_P(obj) == IS_OBJECT) {
3729 				return zend_create_member_string(Z_OBJCE_P(obj)->name, Z_STR_P(method));
3730 			} else {
3731 				return ZSTR_KNOWN(ZEND_STR_ARRAY_CAPITALIZED);
3732 			}
3733 		}
3734 		case IS_OBJECT:
3735 		{
3736 			zend_class_entry *ce = Z_OBJCE_P(callable);
3737 			return zend_string_concat2(
3738 				ZSTR_VAL(ce->name), ZSTR_LEN(ce->name),
3739 				"::__invoke", sizeof("::__invoke") - 1);
3740 		}
3741 		case IS_REFERENCE:
3742 			callable = Z_REFVAL_P(callable);
3743 			goto try_again;
3744 		default:
3745 			return zval_get_string_func(callable);
3746 	}
3747 }
3748 /* }}} */
3749 
zend_get_callable_name(zval * callable)3750 ZEND_API zend_string *zend_get_callable_name(zval *callable) /* {{{ */
3751 {
3752 	return zend_get_callable_name_ex(callable, NULL);
3753 }
3754 /* }}} */
3755 
zend_is_callable_at_frame(zval * callable,zend_object * object,zend_execute_data * frame,uint32_t check_flags,zend_fcall_info_cache * fcc,char ** error)3756 ZEND_API bool zend_is_callable_at_frame(
3757 		zval *callable, zend_object *object, zend_execute_data *frame,
3758 		uint32_t check_flags, zend_fcall_info_cache *fcc, char **error) /* {{{ */
3759 {
3760 	bool ret;
3761 	zend_fcall_info_cache fcc_local;
3762 	bool strict_class = 0;
3763 
3764 	if (fcc == NULL) {
3765 		fcc = &fcc_local;
3766 	}
3767 	if (error) {
3768 		*error = NULL;
3769 	}
3770 
3771 	fcc->calling_scope = NULL;
3772 	fcc->called_scope = NULL;
3773 	fcc->function_handler = NULL;
3774 	fcc->object = NULL;
3775 
3776 again:
3777 	switch (Z_TYPE_P(callable)) {
3778 		case IS_STRING:
3779 			if (object) {
3780 				fcc->object = object;
3781 				fcc->calling_scope = object->ce;
3782 			}
3783 
3784 			if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3785 				fcc->called_scope = fcc->calling_scope;
3786 				return 1;
3787 			}
3788 
3789 check_func:
3790 			ret = zend_is_callable_check_func(check_flags, callable, frame, fcc, strict_class, error);
3791 			if (fcc == &fcc_local) {
3792 				zend_release_fcall_info_cache(fcc);
3793 			}
3794 			return ret;
3795 
3796 		case IS_ARRAY:
3797 			{
3798 				zval *method = NULL;
3799 				zval *obj = NULL;
3800 
3801 				if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
3802 					obj = zend_hash_index_find(Z_ARRVAL_P(callable), 0);
3803 					method = zend_hash_index_find(Z_ARRVAL_P(callable), 1);
3804 				}
3805 
3806 				do {
3807 					if (obj == NULL || method == NULL) {
3808 						break;
3809 					}
3810 
3811 					ZVAL_DEREF(method);
3812 					if (Z_TYPE_P(method) != IS_STRING) {
3813 						break;
3814 					}
3815 
3816 					ZVAL_DEREF(obj);
3817 					if (Z_TYPE_P(obj) == IS_STRING) {
3818 						if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3819 							return 1;
3820 						}
3821 
3822 						if (!zend_is_callable_check_class(Z_STR_P(obj), get_scope(frame), frame, fcc, &strict_class, error)) {
3823 							return 0;
3824 						}
3825 
3826 					} else if (Z_TYPE_P(obj) == IS_OBJECT) {
3827 
3828 						fcc->calling_scope = Z_OBJCE_P(obj); /* TBFixed: what if it's overloaded? */
3829 
3830 						fcc->object = Z_OBJ_P(obj);
3831 
3832 						if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3833 							fcc->called_scope = fcc->calling_scope;
3834 							return 1;
3835 						}
3836 					} else {
3837 						break;
3838 					}
3839 
3840 					callable = method;
3841 					goto check_func;
3842 
3843 				} while (0);
3844 				if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
3845 					if (!obj || (!Z_ISREF_P(obj)?
3846 								(Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_OBJECT) :
3847 								(Z_TYPE_P(Z_REFVAL_P(obj)) != IS_STRING && Z_TYPE_P(Z_REFVAL_P(obj)) != IS_OBJECT))) {
3848 						if (error) *error = estrdup("first array member is not a valid class name or object");
3849 					} else {
3850 						if (error) *error = estrdup("second array member is not a valid method");
3851 					}
3852 				} else {
3853 					if (error) *error = estrdup("array must have exactly two members");
3854 				}
3855 			}
3856 			return 0;
3857 		case IS_OBJECT:
3858 			if (Z_OBJ_HANDLER_P(callable, get_closure) && Z_OBJ_HANDLER_P(callable, get_closure)(Z_OBJ_P(callable), &fcc->calling_scope, &fcc->function_handler, &fcc->object, 1) == SUCCESS) {
3859 				fcc->called_scope = fcc->calling_scope;
3860 				if (fcc == &fcc_local) {
3861 					zend_release_fcall_info_cache(fcc);
3862 				}
3863 				return 1;
3864 			}
3865 			if (error) *error = estrdup("no array or string given");
3866 			return 0;
3867 		case IS_REFERENCE:
3868 			callable = Z_REFVAL_P(callable);
3869 			goto again;
3870 		default:
3871 			if (error) *error = estrdup("no array or string given");
3872 			return 0;
3873 	}
3874 }
3875 /* }}} */
3876 
zend_is_callable_ex(zval * callable,zend_object * object,uint32_t check_flags,zend_string ** callable_name,zend_fcall_info_cache * fcc,char ** error)3877 ZEND_API bool zend_is_callable_ex(zval *callable, zend_object *object, uint32_t check_flags, zend_string **callable_name, zend_fcall_info_cache *fcc, char **error) /* {{{ */
3878 {
3879 	/* Determine callability at the first parent user frame. */
3880 	zend_execute_data *frame = EG(current_execute_data);
3881 	while (frame && (!frame->func || !ZEND_USER_CODE(frame->func->type))) {
3882 		frame = frame->prev_execute_data;
3883 	}
3884 
3885 	bool ret = zend_is_callable_at_frame(callable, object, frame, check_flags, fcc, error);
3886 	if (callable_name) {
3887 		*callable_name = zend_get_callable_name_ex(callable, object);
3888 	}
3889 	return ret;
3890 }
3891 
zend_is_callable(zval * callable,uint32_t check_flags,zend_string ** callable_name)3892 ZEND_API bool zend_is_callable(zval *callable, uint32_t check_flags, zend_string **callable_name) /* {{{ */
3893 {
3894 	return zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, NULL);
3895 }
3896 /* }}} */
3897 
zend_make_callable(zval * callable,zend_string ** callable_name)3898 ZEND_API bool zend_make_callable(zval *callable, zend_string **callable_name) /* {{{ */
3899 {
3900 	zend_fcall_info_cache fcc;
3901 
3902 	if (zend_is_callable_ex(callable, NULL, 0, callable_name, &fcc, NULL)) {
3903 		if (Z_TYPE_P(callable) == IS_STRING && fcc.calling_scope) {
3904 			zval_ptr_dtor_str(callable);
3905 			array_init(callable);
3906 			add_next_index_str(callable, zend_string_copy(fcc.calling_scope->name));
3907 			add_next_index_str(callable, zend_string_copy(fcc.function_handler->common.function_name));
3908 		}
3909 		zend_release_fcall_info_cache(&fcc);
3910 		return 1;
3911 	}
3912 	return 0;
3913 }
3914 /* }}} */
3915 
zend_fcall_info_init(zval * callable,uint32_t check_flags,zend_fcall_info * fci,zend_fcall_info_cache * fcc,zend_string ** callable_name,char ** error)3916 ZEND_API zend_result zend_fcall_info_init(zval *callable, uint32_t check_flags, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string **callable_name, char **error) /* {{{ */
3917 {
3918 	if (!zend_is_callable_ex(callable, NULL, check_flags, callable_name, fcc, error)) {
3919 		return FAILURE;
3920 	}
3921 
3922 	fci->size = sizeof(*fci);
3923 	fci->object = fcc->object;
3924 	ZVAL_COPY_VALUE(&fci->function_name, callable);
3925 	fci->retval = NULL;
3926 	fci->param_count = 0;
3927 	fci->params = NULL;
3928 	fci->named_params = NULL;
3929 
3930 	return SUCCESS;
3931 }
3932 /* }}} */
3933 
zend_fcall_info_args_clear(zend_fcall_info * fci,bool free_mem)3934 ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, bool free_mem) /* {{{ */
3935 {
3936 	if (fci->params) {
3937 		zval *p = fci->params;
3938 		zval *end = p + fci->param_count;
3939 
3940 		while (p != end) {
3941 			i_zval_ptr_dtor(p);
3942 			p++;
3943 		}
3944 		if (free_mem) {
3945 			efree(fci->params);
3946 			fci->params = NULL;
3947 		}
3948 	}
3949 	fci->param_count = 0;
3950 }
3951 /* }}} */
3952 
zend_fcall_info_args_save(zend_fcall_info * fci,uint32_t * param_count,zval ** params)3953 ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, uint32_t *param_count, zval **params) /* {{{ */
3954 {
3955 	*param_count = fci->param_count;
3956 	*params = fci->params;
3957 	fci->param_count = 0;
3958 	fci->params = NULL;
3959 }
3960 /* }}} */
3961 
zend_fcall_info_args_restore(zend_fcall_info * fci,uint32_t param_count,zval * params)3962 ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, uint32_t param_count, zval *params) /* {{{ */
3963 {
3964 	zend_fcall_info_args_clear(fci, 1);
3965 	fci->param_count = param_count;
3966 	fci->params = params;
3967 }
3968 /* }}} */
3969 
zend_fcall_info_args_ex(zend_fcall_info * fci,zend_function * func,zval * args)3970 ZEND_API zend_result zend_fcall_info_args_ex(zend_fcall_info *fci, zend_function *func, zval *args) /* {{{ */
3971 {
3972 	zval *arg, *params;
3973 	uint32_t n = 1;
3974 
3975 	zend_fcall_info_args_clear(fci, !args);
3976 
3977 	if (!args) {
3978 		return SUCCESS;
3979 	}
3980 
3981 	if (Z_TYPE_P(args) != IS_ARRAY) {
3982 		return FAILURE;
3983 	}
3984 
3985 	fci->param_count = zend_hash_num_elements(Z_ARRVAL_P(args));
3986 	fci->params = params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
3987 
3988 	ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args), arg) {
3989 		if (func && !Z_ISREF_P(arg) && ARG_SHOULD_BE_SENT_BY_REF(func, n)) {
3990 			ZVAL_NEW_REF(params, arg);
3991 			Z_TRY_ADDREF_P(arg);
3992 		} else {
3993 			ZVAL_COPY(params, arg);
3994 		}
3995 		params++;
3996 		n++;
3997 	} ZEND_HASH_FOREACH_END();
3998 
3999 	return SUCCESS;
4000 }
4001 /* }}} */
4002 
zend_fcall_info_args(zend_fcall_info * fci,zval * args)4003 ZEND_API zend_result zend_fcall_info_args(zend_fcall_info *fci, zval *args) /* {{{ */
4004 {
4005 	return zend_fcall_info_args_ex(fci, NULL, args);
4006 }
4007 /* }}} */
4008 
zend_fcall_info_argp(zend_fcall_info * fci,uint32_t argc,zval * argv)4009 ZEND_API void zend_fcall_info_argp(zend_fcall_info *fci, uint32_t argc, zval *argv) /* {{{ */
4010 {
4011 	zend_fcall_info_args_clear(fci, !argc);
4012 
4013 	if (argc) {
4014 		fci->param_count = argc;
4015 		fci->params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
4016 
4017 		for (uint32_t i = 0; i < argc; ++i) {
4018 			ZVAL_COPY(&fci->params[i], &argv[i]);
4019 		}
4020 	}
4021 }
4022 /* }}} */
4023 
zend_fcall_info_argv(zend_fcall_info * fci,uint32_t argc,va_list * argv)4024 ZEND_API void zend_fcall_info_argv(zend_fcall_info *fci, uint32_t argc, va_list *argv) /* {{{ */
4025 {
4026 	zend_fcall_info_args_clear(fci, !argc);
4027 
4028 	if (argc) {
4029 		zval *arg;
4030 		fci->param_count = argc;
4031 		fci->params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
4032 
4033 		for (uint32_t i = 0; i < argc; ++i) {
4034 			arg = va_arg(*argv, zval *);
4035 			ZVAL_COPY(&fci->params[i], arg);
4036 		}
4037 	}
4038 }
4039 /* }}} */
4040 
zend_fcall_info_argn(zend_fcall_info * fci,uint32_t argc,...)4041 ZEND_API void zend_fcall_info_argn(zend_fcall_info *fci, uint32_t argc, ...) /* {{{ */
4042 {
4043 	va_list argv;
4044 
4045 	va_start(argv, argc);
4046 	zend_fcall_info_argv(fci, argc, &argv);
4047 	va_end(argv);
4048 }
4049 /* }}} */
4050 
zend_fcall_info_call(zend_fcall_info * fci,zend_fcall_info_cache * fcc,zval * retval_ptr,zval * args)4051 ZEND_API zend_result zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval *retval_ptr, zval *args) /* {{{ */
4052 {
4053 	zval retval, *org_params = NULL;
4054 	uint32_t org_count = 0;
4055 	zend_result result;
4056 
4057 	fci->retval = retval_ptr ? retval_ptr : &retval;
4058 	if (args) {
4059 		zend_fcall_info_args_save(fci, &org_count, &org_params);
4060 		zend_fcall_info_args(fci, args);
4061 	}
4062 	result = zend_call_function(fci, fcc);
4063 
4064 	if (!retval_ptr && Z_TYPE(retval) != IS_UNDEF) {
4065 		zval_ptr_dtor(&retval);
4066 	}
4067 	if (args) {
4068 		zend_fcall_info_args_restore(fci, org_count, org_params);
4069 	}
4070 	return result;
4071 }
4072 /* }}} */
4073 
zend_get_module_version(const char * module_name)4074 ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */
4075 {
4076 	zend_string *lname;
4077 	size_t name_len = strlen(module_name);
4078 	zend_module_entry *module;
4079 
4080 	lname = zend_string_alloc(name_len, 0);
4081 	zend_str_tolower_copy(ZSTR_VAL(lname), module_name, name_len);
4082 	module = zend_hash_find_ptr(&module_registry, lname);
4083 	zend_string_efree(lname);
4084 	return module ? module->version : NULL;
4085 }
4086 /* }}} */
4087 
is_persistent_class(zend_class_entry * ce)4088 static zend_always_inline bool is_persistent_class(zend_class_entry *ce) {
4089 	return (ce->type & ZEND_INTERNAL_CLASS)
4090 		&& ce->info.internal.module->type == MODULE_PERSISTENT;
4091 }
4092 
zend_declare_typed_property(zend_class_entry * ce,zend_string * name,zval * property,int access_type,zend_string * doc_comment,zend_type type)4093 ZEND_API zend_property_info *zend_declare_typed_property(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment, zend_type type) /* {{{ */
4094 {
4095 	zend_property_info *property_info, *property_info_ptr;
4096 
4097 	if (ZEND_TYPE_IS_SET(type)) {
4098 		ce->ce_flags |= ZEND_ACC_HAS_TYPE_HINTS;
4099 	}
4100 
4101 	if (ce->type == ZEND_INTERNAL_CLASS) {
4102 		property_info = pemalloc(sizeof(zend_property_info), 1);
4103 	} else {
4104 		property_info = zend_arena_alloc(&CG(arena), sizeof(zend_property_info));
4105 		if (Z_TYPE_P(property) == IS_CONSTANT_AST) {
4106 			ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
4107 			if (access_type & ZEND_ACC_STATIC) {
4108 				ce->ce_flags |= ZEND_ACC_HAS_AST_STATICS;
4109 			} else {
4110 				ce->ce_flags |= ZEND_ACC_HAS_AST_PROPERTIES;
4111 			}
4112 		}
4113 	}
4114 
4115 	if (Z_TYPE_P(property) == IS_STRING && !ZSTR_IS_INTERNED(Z_STR_P(property))) {
4116 		zval_make_interned_string(property);
4117 	}
4118 
4119 	if (!(access_type & ZEND_ACC_PPP_MASK)) {
4120 		access_type |= ZEND_ACC_PUBLIC;
4121 	}
4122 	if (access_type & ZEND_ACC_STATIC) {
4123 		if ((property_info_ptr = zend_hash_find_ptr(&ce->properties_info, name)) != NULL &&
4124 		    (property_info_ptr->flags & ZEND_ACC_STATIC) != 0) {
4125 			property_info->offset = property_info_ptr->offset;
4126 			zval_ptr_dtor(&ce->default_static_members_table[property_info->offset]);
4127 			if (property_info_ptr->doc_comment && property_info_ptr->ce == ce) {
4128 				zend_string_release(property_info_ptr->doc_comment);
4129 			}
4130 			zend_hash_del(&ce->properties_info, name);
4131 		} else {
4132 			property_info->offset = ce->default_static_members_count++;
4133 			ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
4134 		}
4135 		ZVAL_COPY_VALUE(&ce->default_static_members_table[property_info->offset], property);
4136 		if (!ZEND_MAP_PTR(ce->static_members_table)) {
4137 			if (ce->type == ZEND_INTERNAL_CLASS &&
4138 					ce->info.internal.module->type == MODULE_PERSISTENT) {
4139 				ZEND_MAP_PTR_NEW(ce->static_members_table);
4140 			} else {
4141 				ZEND_MAP_PTR_INIT(ce->static_members_table,
4142 					zend_arena_alloc(&CG(arena), sizeof(zval **)));
4143 				ZEND_MAP_PTR_SET(ce->static_members_table, NULL);
4144 			}
4145 		}
4146 	} else {
4147 		zval *property_default_ptr;
4148 		if ((property_info_ptr = zend_hash_find_ptr(&ce->properties_info, name)) != NULL &&
4149 		    (property_info_ptr->flags & ZEND_ACC_STATIC) == 0) {
4150 			property_info->offset = property_info_ptr->offset;
4151 			zval_ptr_dtor(&ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)]);
4152 			if (property_info_ptr->doc_comment && property_info_ptr->ce == ce) {
4153 				zend_string_release_ex(property_info_ptr->doc_comment, 1);
4154 			}
4155 			zend_hash_del(&ce->properties_info, name);
4156 
4157 			ZEND_ASSERT(ce->type == ZEND_INTERNAL_CLASS);
4158 			ZEND_ASSERT(ce->properties_info_table != NULL);
4159 			ce->properties_info_table[OBJ_PROP_TO_NUM(property_info->offset)] = property_info;
4160 		} else {
4161 			property_info->offset = OBJ_PROP_TO_OFFSET(ce->default_properties_count);
4162 			ce->default_properties_count++;
4163 			ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
4164 
4165 			/* For user classes this is handled during linking */
4166 			if (ce->type == ZEND_INTERNAL_CLASS) {
4167 				ce->properties_info_table = perealloc(ce->properties_info_table, sizeof(zend_property_info *) * ce->default_properties_count, 1);
4168 				ce->properties_info_table[ce->default_properties_count - 1] = property_info;
4169 			}
4170 		}
4171 		property_default_ptr = &ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)];
4172 		ZVAL_COPY_VALUE(property_default_ptr, property);
4173 		Z_PROP_FLAG_P(property_default_ptr) = Z_ISUNDEF_P(property) ? IS_PROP_UNINIT : 0;
4174 	}
4175 	if (ce->type & ZEND_INTERNAL_CLASS) {
4176 		/* Must be interned to avoid ZTS data races */
4177 		if (is_persistent_class(ce)) {
4178 			name = zend_new_interned_string(zend_string_copy(name));
4179 		}
4180 
4181 		if (Z_REFCOUNTED_P(property)) {
4182 			zend_error_noreturn(E_CORE_ERROR, "Internal zvals cannot be refcounted");
4183 		}
4184 	}
4185 
4186 	if (access_type & ZEND_ACC_PUBLIC) {
4187 		property_info->name = zend_string_copy(name);
4188 	} else if (access_type & ZEND_ACC_PRIVATE) {
4189 		property_info->name = zend_mangle_property_name(ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), ZSTR_VAL(name), ZSTR_LEN(name), is_persistent_class(ce));
4190 	} else {
4191 		ZEND_ASSERT(access_type & ZEND_ACC_PROTECTED);
4192 		property_info->name = zend_mangle_property_name("*", 1, ZSTR_VAL(name), ZSTR_LEN(name), is_persistent_class(ce));
4193 	}
4194 
4195 	property_info->name = zend_new_interned_string(property_info->name);
4196 	property_info->flags = access_type;
4197 	property_info->doc_comment = doc_comment;
4198 	property_info->attributes = NULL;
4199 	property_info->ce = ce;
4200 	property_info->type = type;
4201 
4202 	if (is_persistent_class(ce)) {
4203 		zend_type *single_type;
4204 		ZEND_TYPE_FOREACH(property_info->type, single_type) {
4205 			if (ZEND_TYPE_HAS_NAME(*single_type)) {
4206 				zend_string *name = zend_new_interned_string(ZEND_TYPE_NAME(*single_type));
4207 				ZEND_TYPE_SET_PTR(*single_type, name);
4208 				zend_alloc_ce_cache(name);
4209 			}
4210 		} ZEND_TYPE_FOREACH_END();
4211 	}
4212 
4213 	zend_hash_update_ptr(&ce->properties_info, name, property_info);
4214 
4215 	return property_info;
4216 }
4217 /* }}} */
4218 
zend_try_assign_typed_ref_ex(zend_reference * ref,zval * val,bool strict)4219 ZEND_API zend_result zend_try_assign_typed_ref_ex(zend_reference *ref, zval *val, bool strict) /* {{{ */
4220 {
4221 	if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, val, strict))) {
4222 		zval_ptr_dtor(val);
4223 		return FAILURE;
4224 	} else {
4225 		zval_ptr_dtor(&ref->val);
4226 		ZVAL_COPY_VALUE(&ref->val, val);
4227 		return SUCCESS;
4228 	}
4229 }
4230 /* }}} */
4231 
zend_try_assign_typed_ref(zend_reference * ref,zval * val)4232 ZEND_API zend_result zend_try_assign_typed_ref(zend_reference *ref, zval *val) /* {{{ */
4233 {
4234 	return zend_try_assign_typed_ref_ex(ref, val, ZEND_ARG_USES_STRICT_TYPES());
4235 }
4236 /* }}} */
4237 
zend_try_assign_typed_ref_null(zend_reference * ref)4238 ZEND_API zend_result zend_try_assign_typed_ref_null(zend_reference *ref) /* {{{ */
4239 {
4240 	zval tmp;
4241 
4242 	ZVAL_NULL(&tmp);
4243 	return zend_try_assign_typed_ref(ref, &tmp);
4244 }
4245 /* }}} */
4246 
zend_try_assign_typed_ref_bool(zend_reference * ref,bool val)4247 ZEND_API zend_result zend_try_assign_typed_ref_bool(zend_reference *ref, bool val) /* {{{ */
4248 {
4249 	zval tmp;
4250 
4251 	ZVAL_BOOL(&tmp, val);
4252 	return zend_try_assign_typed_ref(ref, &tmp);
4253 }
4254 /* }}} */
4255 
zend_try_assign_typed_ref_long(zend_reference * ref,zend_long lval)4256 ZEND_API zend_result zend_try_assign_typed_ref_long(zend_reference *ref, zend_long lval) /* {{{ */
4257 {
4258 	zval tmp;
4259 
4260 	ZVAL_LONG(&tmp, lval);
4261 	return zend_try_assign_typed_ref(ref, &tmp);
4262 }
4263 /* }}} */
4264 
zend_try_assign_typed_ref_double(zend_reference * ref,double dval)4265 ZEND_API zend_result zend_try_assign_typed_ref_double(zend_reference *ref, double dval) /* {{{ */
4266 {
4267 	zval tmp;
4268 
4269 	ZVAL_DOUBLE(&tmp, dval);
4270 	return zend_try_assign_typed_ref(ref, &tmp);
4271 }
4272 /* }}} */
4273 
zend_try_assign_typed_ref_empty_string(zend_reference * ref)4274 ZEND_API zend_result zend_try_assign_typed_ref_empty_string(zend_reference *ref) /* {{{ */
4275 {
4276 	zval tmp;
4277 
4278 	ZVAL_EMPTY_STRING(&tmp);
4279 	return zend_try_assign_typed_ref(ref, &tmp);
4280 }
4281 /* }}} */
4282 
zend_try_assign_typed_ref_str(zend_reference * ref,zend_string * str)4283 ZEND_API zend_result zend_try_assign_typed_ref_str(zend_reference *ref, zend_string *str) /* {{{ */
4284 {
4285 	zval tmp;
4286 
4287 	ZVAL_STR(&tmp, str);
4288 	return zend_try_assign_typed_ref(ref, &tmp);
4289 }
4290 /* }}} */
4291 
zend_try_assign_typed_ref_string(zend_reference * ref,const char * string)4292 ZEND_API zend_result zend_try_assign_typed_ref_string(zend_reference *ref, const char *string) /* {{{ */
4293 {
4294 	zval tmp;
4295 
4296 	ZVAL_STRING(&tmp, string);
4297 	return zend_try_assign_typed_ref(ref, &tmp);
4298 }
4299 /* }}} */
4300 
zend_try_assign_typed_ref_stringl(zend_reference * ref,const char * string,size_t len)4301 ZEND_API zend_result zend_try_assign_typed_ref_stringl(zend_reference *ref, const char *string, size_t len) /* {{{ */
4302 {
4303 	zval tmp;
4304 
4305 	ZVAL_STRINGL(&tmp, string, len);
4306 	return zend_try_assign_typed_ref(ref, &tmp);
4307 }
4308 /* }}} */
4309 
zend_try_assign_typed_ref_arr(zend_reference * ref,zend_array * arr)4310 ZEND_API zend_result zend_try_assign_typed_ref_arr(zend_reference *ref, zend_array *arr) /* {{{ */
4311 {
4312 	zval tmp;
4313 
4314 	ZVAL_ARR(&tmp, arr);
4315 	return zend_try_assign_typed_ref(ref, &tmp);
4316 }
4317 /* }}} */
4318 
zend_try_assign_typed_ref_res(zend_reference * ref,zend_resource * res)4319 ZEND_API zend_result zend_try_assign_typed_ref_res(zend_reference *ref, zend_resource *res) /* {{{ */
4320 {
4321 	zval tmp;
4322 
4323 	ZVAL_RES(&tmp, res);
4324 	return zend_try_assign_typed_ref(ref, &tmp);
4325 }
4326 /* }}} */
4327 
zend_try_assign_typed_ref_zval(zend_reference * ref,zval * zv)4328 ZEND_API zend_result zend_try_assign_typed_ref_zval(zend_reference *ref, zval *zv) /* {{{ */
4329 {
4330 	zval tmp;
4331 
4332 	ZVAL_COPY_VALUE(&tmp, zv);
4333 	return zend_try_assign_typed_ref(ref, &tmp);
4334 }
4335 /* }}} */
4336 
zend_try_assign_typed_ref_zval_ex(zend_reference * ref,zval * zv,bool strict)4337 ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval *zv, bool strict) /* {{{ */
4338 {
4339 	zval tmp;
4340 
4341 	ZVAL_COPY_VALUE(&tmp, zv);
4342 	return zend_try_assign_typed_ref_ex(ref, &tmp, strict);
4343 }
4344 /* }}} */
4345 
zend_declare_property_ex(zend_class_entry * ce,zend_string * name,zval * property,int access_type,zend_string * doc_comment)4346 ZEND_API void zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment) /* {{{ */
4347 {
4348 	zend_declare_typed_property(ce, name, property, access_type, doc_comment, (zend_type) ZEND_TYPE_INIT_NONE(0));
4349 }
4350 /* }}} */
4351 
zend_declare_property(zend_class_entry * ce,const char * name,size_t name_length,zval * property,int access_type)4352 ZEND_API void zend_declare_property(zend_class_entry *ce, const char *name, size_t name_length, zval *property, int access_type) /* {{{ */
4353 {
4354 	zend_string *key = zend_string_init(name, name_length, is_persistent_class(ce));
4355 	zend_declare_property_ex(ce, key, property, access_type, NULL);
4356 	zend_string_release(key);
4357 }
4358 /* }}} */
4359 
zend_declare_property_null(zend_class_entry * ce,const char * name,size_t name_length,int access_type)4360 ZEND_API void zend_declare_property_null(zend_class_entry *ce, const char *name, size_t name_length, int access_type) /* {{{ */
4361 {
4362 	zval property;
4363 
4364 	ZVAL_NULL(&property);
4365 	zend_declare_property(ce, name, name_length, &property, access_type);
4366 }
4367 /* }}} */
4368 
zend_declare_property_bool(zend_class_entry * ce,const char * name,size_t name_length,zend_long value,int access_type)4369 ZEND_API void zend_declare_property_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type) /* {{{ */
4370 {
4371 	zval property;
4372 
4373 	ZVAL_BOOL(&property, value);
4374 	zend_declare_property(ce, name, name_length, &property, access_type);
4375 }
4376 /* }}} */
4377 
zend_declare_property_long(zend_class_entry * ce,const char * name,size_t name_length,zend_long value,int access_type)4378 ZEND_API void zend_declare_property_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type) /* {{{ */
4379 {
4380 	zval property;
4381 
4382 	ZVAL_LONG(&property, value);
4383 	zend_declare_property(ce, name, name_length, &property, access_type);
4384 }
4385 /* }}} */
4386 
zend_declare_property_double(zend_class_entry * ce,const char * name,size_t name_length,double value,int access_type)4387 ZEND_API void zend_declare_property_double(zend_class_entry *ce, const char *name, size_t name_length, double value, int access_type) /* {{{ */
4388 {
4389 	zval property;
4390 
4391 	ZVAL_DOUBLE(&property, value);
4392 	zend_declare_property(ce, name, name_length, &property, access_type);
4393 }
4394 /* }}} */
4395 
zend_declare_property_string(zend_class_entry * ce,const char * name,size_t name_length,const char * value,int access_type)4396 ZEND_API void zend_declare_property_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value, int access_type) /* {{{ */
4397 {
4398 	zval property;
4399 
4400 	ZVAL_NEW_STR(&property, zend_string_init(value, strlen(value), ce->type & ZEND_INTERNAL_CLASS));
4401 	zend_declare_property(ce, name, name_length, &property, access_type);
4402 }
4403 /* }}} */
4404 
zend_declare_property_stringl(zend_class_entry * ce,const char * name,size_t name_length,const char * value,size_t value_len,int access_type)4405 ZEND_API void zend_declare_property_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_len, int access_type) /* {{{ */
4406 {
4407 	zval property;
4408 
4409 	ZVAL_NEW_STR(&property, zend_string_init(value, value_len, ce->type & ZEND_INTERNAL_CLASS));
4410 	zend_declare_property(ce, name, name_length, &property, access_type);
4411 }
4412 /* }}} */
4413 
zend_declare_class_constant_ex(zend_class_entry * ce,zend_string * name,zval * value,int flags,zend_string * doc_comment)4414 ZEND_API zend_class_constant *zend_declare_class_constant_ex(zend_class_entry *ce, zend_string *name, zval *value, int flags, zend_string *doc_comment) /* {{{ */
4415 {
4416 	zend_class_constant *c;
4417 
4418 	if (ce->ce_flags & ZEND_ACC_INTERFACE) {
4419 		if (!(flags & ZEND_ACC_PUBLIC)) {
4420 			zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface constant %s::%s must be public", ZSTR_VAL(ce->name), ZSTR_VAL(name));
4421 		}
4422 	}
4423 
4424 	if (zend_string_equals_literal_ci(name, "class")) {
4425 		zend_error_noreturn(ce->type == ZEND_INTERNAL_CLASS ? E_CORE_ERROR : E_COMPILE_ERROR,
4426 				"A class constant must not be called 'class'; it is reserved for class name fetching");
4427 	}
4428 
4429 	if (Z_TYPE_P(value) == IS_STRING && !ZSTR_IS_INTERNED(Z_STR_P(value))) {
4430 		zval_make_interned_string(value);
4431 	}
4432 
4433 	if (ce->type == ZEND_INTERNAL_CLASS) {
4434 		c = pemalloc(sizeof(zend_class_constant), 1);
4435 	} else {
4436 		c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
4437 	}
4438 	ZVAL_COPY_VALUE(&c->value, value);
4439 	ZEND_CLASS_CONST_FLAGS(c) = flags;
4440 	c->doc_comment = doc_comment;
4441 	c->attributes = NULL;
4442 	c->ce = ce;
4443 	if (Z_TYPE_P(value) == IS_CONSTANT_AST) {
4444 		ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
4445 		ce->ce_flags |= ZEND_ACC_HAS_AST_CONSTANTS;
4446 		if (ce->type == ZEND_INTERNAL_CLASS && !ZEND_MAP_PTR(ce->mutable_data)) {
4447 			ZEND_MAP_PTR_NEW(ce->mutable_data);
4448 		}
4449 	}
4450 
4451 	if (!zend_hash_add_ptr(&ce->constants_table, name, c)) {
4452 		zend_error_noreturn(ce->type == ZEND_INTERNAL_CLASS ? E_CORE_ERROR : E_COMPILE_ERROR,
4453 			"Cannot redefine class constant %s::%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
4454 	}
4455 
4456 	return c;
4457 }
4458 /* }}} */
4459 
zend_declare_class_constant(zend_class_entry * ce,const char * name,size_t name_length,zval * value)4460 ZEND_API void zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value) /* {{{ */
4461 {
4462 	zend_string *key;
4463 
4464 	if (ce->type == ZEND_INTERNAL_CLASS) {
4465 		key = zend_string_init_interned(name, name_length, 1);
4466 	} else {
4467 		key = zend_string_init(name, name_length, 0);
4468 	}
4469 	zend_declare_class_constant_ex(ce, key, value, ZEND_ACC_PUBLIC, NULL);
4470 	zend_string_release(key);
4471 }
4472 /* }}} */
4473 
zend_declare_class_constant_null(zend_class_entry * ce,const char * name,size_t name_length)4474 ZEND_API void zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length) /* {{{ */
4475 {
4476 	zval constant;
4477 
4478 	ZVAL_NULL(&constant);
4479 	zend_declare_class_constant(ce, name, name_length, &constant);
4480 }
4481 /* }}} */
4482 
zend_declare_class_constant_long(zend_class_entry * ce,const char * name,size_t name_length,zend_long value)4483 ZEND_API void zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value) /* {{{ */
4484 {
4485 	zval constant;
4486 
4487 	ZVAL_LONG(&constant, value);
4488 	zend_declare_class_constant(ce, name, name_length, &constant);
4489 }
4490 /* }}} */
4491 
zend_declare_class_constant_bool(zend_class_entry * ce,const char * name,size_t name_length,bool value)4492 ZEND_API void zend_declare_class_constant_bool(zend_class_entry *ce, const char *name, size_t name_length, bool value) /* {{{ */
4493 {
4494 	zval constant;
4495 
4496 	ZVAL_BOOL(&constant, value);
4497 	zend_declare_class_constant(ce, name, name_length, &constant);
4498 }
4499 /* }}} */
4500 
zend_declare_class_constant_double(zend_class_entry * ce,const char * name,size_t name_length,double value)4501 ZEND_API void zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value) /* {{{ */
4502 {
4503 	zval constant;
4504 
4505 	ZVAL_DOUBLE(&constant, value);
4506 	zend_declare_class_constant(ce, name, name_length, &constant);
4507 }
4508 /* }}} */
4509 
zend_declare_class_constant_stringl(zend_class_entry * ce,const char * name,size_t name_length,const char * value,size_t value_length)4510 ZEND_API void zend_declare_class_constant_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_length) /* {{{ */
4511 {
4512 	zval constant;
4513 
4514 	ZVAL_NEW_STR(&constant, zend_string_init(value, value_length, ce->type & ZEND_INTERNAL_CLASS));
4515 	zend_declare_class_constant(ce, name, name_length, &constant);
4516 }
4517 /* }}} */
4518 
zend_declare_class_constant_string(zend_class_entry * ce,const char * name,size_t name_length,const char * value)4519 ZEND_API void zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value) /* {{{ */
4520 {
4521 	zend_declare_class_constant_stringl(ce, name, name_length, value, strlen(value));
4522 }
4523 /* }}} */
4524 
zend_update_property_ex(zend_class_entry * scope,zend_object * object,zend_string * name,zval * value)4525 ZEND_API void zend_update_property_ex(zend_class_entry *scope, zend_object *object, zend_string *name, zval *value) /* {{{ */
4526 {
4527 	zend_class_entry *old_scope = EG(fake_scope);
4528 
4529 	EG(fake_scope) = scope;
4530 
4531 	object->handlers->write_property(object, name, value, NULL);
4532 
4533 	EG(fake_scope) = old_scope;
4534 }
4535 /* }}} */
4536 
zend_update_property(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,zval * value)4537 ZEND_API void zend_update_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zval *value) /* {{{ */
4538 {
4539 	zend_string *property;
4540 	zend_class_entry *old_scope = EG(fake_scope);
4541 
4542 	EG(fake_scope) = scope;
4543 
4544 	property = zend_string_init(name, name_length, 0);
4545 	object->handlers->write_property(object, property, value, NULL);
4546 	zend_string_release_ex(property, 0);
4547 
4548 	EG(fake_scope) = old_scope;
4549 }
4550 /* }}} */
4551 
zend_update_property_null(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length)4552 ZEND_API void zend_update_property_null(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length) /* {{{ */
4553 {
4554 	zval tmp;
4555 
4556 	ZVAL_NULL(&tmp);
4557 	zend_update_property(scope, object, name, name_length, &tmp);
4558 }
4559 /* }}} */
4560 
zend_unset_property(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length)4561 ZEND_API void zend_unset_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length) /* {{{ */
4562 {
4563 	zend_string *property;
4564 	zend_class_entry *old_scope = EG(fake_scope);
4565 
4566 	EG(fake_scope) = scope;
4567 
4568 	property = zend_string_init(name, name_length, 0);
4569 	object->handlers->unset_property(object, property, 0);
4570 	zend_string_release_ex(property, 0);
4571 
4572 	EG(fake_scope) = old_scope;
4573 }
4574 /* }}} */
4575 
zend_update_property_bool(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,zend_long value)4576 ZEND_API void zend_update_property_bool(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_long value) /* {{{ */
4577 {
4578 	zval tmp;
4579 
4580 	ZVAL_BOOL(&tmp, value);
4581 	zend_update_property(scope, object, name, name_length, &tmp);
4582 }
4583 /* }}} */
4584 
zend_update_property_long(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,zend_long value)4585 ZEND_API void zend_update_property_long(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_long value) /* {{{ */
4586 {
4587 	zval tmp;
4588 
4589 	ZVAL_LONG(&tmp, value);
4590 	zend_update_property(scope, object, name, name_length, &tmp);
4591 }
4592 /* }}} */
4593 
zend_update_property_double(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,double value)4594 ZEND_API void zend_update_property_double(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, double value) /* {{{ */
4595 {
4596 	zval tmp;
4597 
4598 	ZVAL_DOUBLE(&tmp, value);
4599 	zend_update_property(scope, object, name, name_length, &tmp);
4600 }
4601 /* }}} */
4602 
zend_update_property_str(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,zend_string * value)4603 ZEND_API void zend_update_property_str(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_string *value) /* {{{ */
4604 {
4605 	zval tmp;
4606 
4607 	ZVAL_STR(&tmp, value);
4608 	zend_update_property(scope, object, name, name_length, &tmp);
4609 }
4610 /* }}} */
4611 
zend_update_property_string(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,const char * value)4612 ZEND_API void zend_update_property_string(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, const char *value) /* {{{ */
4613 {
4614 	zval tmp;
4615 
4616 	ZVAL_STRING(&tmp, value);
4617 	Z_SET_REFCOUNT(tmp, 0);
4618 	zend_update_property(scope, object, name, name_length, &tmp);
4619 }
4620 /* }}} */
4621 
zend_update_property_stringl(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,const char * value,size_t value_len)4622 ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, const char *value, size_t value_len) /* {{{ */
4623 {
4624 	zval tmp;
4625 
4626 	ZVAL_STRINGL(&tmp, value, value_len);
4627 	Z_SET_REFCOUNT(tmp, 0);
4628 	zend_update_property(scope, object, name, name_length, &tmp);
4629 }
4630 /* }}} */
4631 
zend_update_static_property_ex(zend_class_entry * scope,zend_string * name,zval * value)4632 ZEND_API zend_result zend_update_static_property_ex(zend_class_entry *scope, zend_string *name, zval *value) /* {{{ */
4633 {
4634 	zval *property, tmp;
4635 	zend_property_info *prop_info;
4636 	zend_class_entry *old_scope = EG(fake_scope);
4637 
4638 	if (UNEXPECTED(!(scope->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
4639 		if (UNEXPECTED(zend_update_class_constants(scope)) != SUCCESS) {
4640 			return FAILURE;
4641 		}
4642 	}
4643 
4644 	EG(fake_scope) = scope;
4645 	property = zend_std_get_static_property_with_info(scope, name, BP_VAR_W, &prop_info);
4646 	EG(fake_scope) = old_scope;
4647 
4648 	if (!property) {
4649 		return FAILURE;
4650 	}
4651 
4652 	ZEND_ASSERT(!Z_ISREF_P(value));
4653 	Z_TRY_ADDREF_P(value);
4654 	if (ZEND_TYPE_IS_SET(prop_info->type)) {
4655 		ZVAL_COPY_VALUE(&tmp, value);
4656 		if (!zend_verify_property_type(prop_info, &tmp, /* strict */ 0)) {
4657 			Z_TRY_DELREF_P(value);
4658 			return FAILURE;
4659 		}
4660 		value = &tmp;
4661 	}
4662 
4663 	zend_assign_to_variable(property, value, IS_TMP_VAR, /* strict */ 0);
4664 	return SUCCESS;
4665 }
4666 /* }}} */
4667 
zend_update_static_property(zend_class_entry * scope,const char * name,size_t name_length,zval * value)4668 ZEND_API zend_result zend_update_static_property(zend_class_entry *scope, const char *name, size_t name_length, zval *value) /* {{{ */
4669 {
4670 	zend_string *key = zend_string_init(name, name_length, 0);
4671 	zend_result retval = zend_update_static_property_ex(scope, key, value);
4672 	zend_string_efree(key);
4673 	return retval;
4674 }
4675 /* }}} */
4676 
zend_update_static_property_null(zend_class_entry * scope,const char * name,size_t name_length)4677 ZEND_API zend_result zend_update_static_property_null(zend_class_entry *scope, const char *name, size_t name_length) /* {{{ */
4678 {
4679 	zval tmp;
4680 
4681 	ZVAL_NULL(&tmp);
4682 	return zend_update_static_property(scope, name, name_length, &tmp);
4683 }
4684 /* }}} */
4685 
zend_update_static_property_bool(zend_class_entry * scope,const char * name,size_t name_length,zend_long value)4686 ZEND_API zend_result zend_update_static_property_bool(zend_class_entry *scope, const char *name, size_t name_length, zend_long value) /* {{{ */
4687 {
4688 	zval tmp;
4689 
4690 	ZVAL_BOOL(&tmp, value);
4691 	return zend_update_static_property(scope, name, name_length, &tmp);
4692 }
4693 /* }}} */
4694 
zend_update_static_property_long(zend_class_entry * scope,const char * name,size_t name_length,zend_long value)4695 ZEND_API zend_result zend_update_static_property_long(zend_class_entry *scope, const char *name, size_t name_length, zend_long value) /* {{{ */
4696 {
4697 	zval tmp;
4698 
4699 	ZVAL_LONG(&tmp, value);
4700 	return zend_update_static_property(scope, name, name_length, &tmp);
4701 }
4702 /* }}} */
4703 
zend_update_static_property_double(zend_class_entry * scope,const char * name,size_t name_length,double value)4704 ZEND_API zend_result zend_update_static_property_double(zend_class_entry *scope, const char *name, size_t name_length, double value) /* {{{ */
4705 {
4706 	zval tmp;
4707 
4708 	ZVAL_DOUBLE(&tmp, value);
4709 	return zend_update_static_property(scope, name, name_length, &tmp);
4710 }
4711 /* }}} */
4712 
zend_update_static_property_string(zend_class_entry * scope,const char * name,size_t name_length,const char * value)4713 ZEND_API zend_result zend_update_static_property_string(zend_class_entry *scope, const char *name, size_t name_length, const char *value) /* {{{ */
4714 {
4715 	zval tmp;
4716 
4717 	ZVAL_STRING(&tmp, value);
4718 	Z_SET_REFCOUNT(tmp, 0);
4719 	return zend_update_static_property(scope, name, name_length, &tmp);
4720 }
4721 /* }}} */
4722 
zend_update_static_property_stringl(zend_class_entry * scope,const char * name,size_t name_length,const char * value,size_t value_len)4723 ZEND_API zend_result zend_update_static_property_stringl(zend_class_entry *scope, const char *name, size_t name_length, const char *value, size_t value_len) /* {{{ */
4724 {
4725 	zval tmp;
4726 
4727 	ZVAL_STRINGL(&tmp, value, value_len);
4728 	Z_SET_REFCOUNT(tmp, 0);
4729 	return zend_update_static_property(scope, name, name_length, &tmp);
4730 }
4731 /* }}} */
4732 
zend_read_property_ex(zend_class_entry * scope,zend_object * object,zend_string * name,bool silent,zval * rv)4733 ZEND_API zval *zend_read_property_ex(zend_class_entry *scope, zend_object *object, zend_string *name, bool silent, zval *rv) /* {{{ */
4734 {
4735 	zval *value;
4736 	zend_class_entry *old_scope = EG(fake_scope);
4737 
4738 	EG(fake_scope) = scope;
4739 
4740 	value = object->handlers->read_property(object, name, silent?BP_VAR_IS:BP_VAR_R, NULL, rv);
4741 
4742 	EG(fake_scope) = old_scope;
4743 	return value;
4744 }
4745 /* }}} */
4746 
zend_read_property(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,bool silent,zval * rv)4747 ZEND_API zval *zend_read_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, bool silent, zval *rv) /* {{{ */
4748 {
4749 	zval *value;
4750 	zend_string *str;
4751 
4752 	str = zend_string_init(name, name_length, 0);
4753 	value = zend_read_property_ex(scope, object, str, silent, rv);
4754 	zend_string_release_ex(str, 0);
4755 	return value;
4756 }
4757 /* }}} */
4758 
zend_read_static_property_ex(zend_class_entry * scope,zend_string * name,bool silent)4759 ZEND_API zval *zend_read_static_property_ex(zend_class_entry *scope, zend_string *name, bool silent) /* {{{ */
4760 {
4761 	zval *property;
4762 	zend_class_entry *old_scope = EG(fake_scope);
4763 
4764 	EG(fake_scope) = scope;
4765 	property = zend_std_get_static_property(scope, name, silent ? BP_VAR_IS : BP_VAR_R);
4766 	EG(fake_scope) = old_scope;
4767 
4768 	return property;
4769 }
4770 /* }}} */
4771 
zend_read_static_property(zend_class_entry * scope,const char * name,size_t name_length,bool silent)4772 ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, size_t name_length, bool silent) /* {{{ */
4773 {
4774 	zend_string *key = zend_string_init(name, name_length, 0);
4775 	zval *property = zend_read_static_property_ex(scope, key, silent);
4776 	zend_string_efree(key);
4777 	return property;
4778 }
4779 /* }}} */
4780 
zend_save_error_handling(zend_error_handling * current)4781 ZEND_API void zend_save_error_handling(zend_error_handling *current) /* {{{ */
4782 {
4783 	current->handling = EG(error_handling);
4784 	current->exception = EG(exception_class);
4785 }
4786 /* }}} */
4787 
zend_replace_error_handling(zend_error_handling_t error_handling,zend_class_entry * exception_class,zend_error_handling * current)4788 ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current) /* {{{ */
4789 {
4790 	if (current) {
4791 		zend_save_error_handling(current);
4792 	}
4793 	ZEND_ASSERT(error_handling == EH_THROW || exception_class == NULL);
4794 	EG(error_handling) = error_handling;
4795 	EG(exception_class) = exception_class;
4796 }
4797 /* }}} */
4798 
zend_restore_error_handling(zend_error_handling * saved)4799 ZEND_API void zend_restore_error_handling(zend_error_handling *saved) /* {{{ */
4800 {
4801 	EG(error_handling) = saved->handling;
4802 	EG(exception_class) = saved->exception;
4803 }
4804 /* }}} */
4805 
zend_get_object_type(const zend_class_entry * ce)4806 ZEND_API ZEND_COLD const char *zend_get_object_type(const zend_class_entry *ce) /* {{{ */
4807 {
4808 	if(ce->ce_flags & ZEND_ACC_TRAIT) {
4809 		return "trait";
4810 	} else if (ce->ce_flags & ZEND_ACC_INTERFACE) {
4811 		return "interface";
4812 	} else {
4813 		return "class";
4814 	}
4815 }
4816 /* }}} */
4817 
zend_is_iterable(zval * iterable)4818 ZEND_API bool zend_is_iterable(zval *iterable) /* {{{ */
4819 {
4820 	switch (Z_TYPE_P(iterable)) {
4821 		case IS_ARRAY:
4822 			return 1;
4823 		case IS_OBJECT:
4824 			return zend_class_implements_interface(Z_OBJCE_P(iterable), zend_ce_traversable);
4825 		default:
4826 			return 0;
4827 	}
4828 }
4829 /* }}} */
4830 
zend_is_countable(zval * countable)4831 ZEND_API bool zend_is_countable(zval *countable) /* {{{ */
4832 {
4833 	switch (Z_TYPE_P(countable)) {
4834 		case IS_ARRAY:
4835 			return 1;
4836 		case IS_OBJECT:
4837 			if (Z_OBJ_HT_P(countable)->count_elements) {
4838 				return 1;
4839 			}
4840 
4841 			return zend_class_implements_interface(Z_OBJCE_P(countable), zend_ce_countable);
4842 		default:
4843 			return 0;
4844 	}
4845 }
4846 /* }}} */
4847 
get_default_via_ast(zval * default_value_zval,const char * default_value)4848 static zend_result get_default_via_ast(zval *default_value_zval, const char *default_value) {
4849 	zend_ast *ast;
4850 	zend_arena *ast_arena;
4851 
4852 	zend_string *code = zend_string_concat3(
4853 		"<?php ", sizeof("<?php ") - 1, default_value, strlen(default_value), ";", 1);
4854 
4855 	ast = zend_compile_string_to_ast(code, &ast_arena, ZSTR_EMPTY_ALLOC());
4856 	zend_string_release(code);
4857 
4858 	if (!ast) {
4859 		return FAILURE;
4860 	}
4861 
4862 	zend_ast_list *statement_list = zend_ast_get_list(ast);
4863 	zend_ast **const_expr_ast_ptr = &statement_list->child[0];
4864 
4865 	zend_arena *original_ast_arena = CG(ast_arena);
4866 	uint32_t original_compiler_options = CG(compiler_options);
4867 	zend_file_context original_file_context;
4868 	CG(ast_arena) = ast_arena;
4869 	/* Disable constant substitution, to make getDefaultValueConstant() work. */
4870 	CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION | ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION;
4871 	zend_file_context_begin(&original_file_context);
4872 	zend_const_expr_to_zval(default_value_zval, const_expr_ast_ptr, /* allow_dynamic */ true);
4873 	CG(ast_arena) = original_ast_arena;
4874 	CG(compiler_options) = original_compiler_options;
4875 	zend_file_context_end(&original_file_context);
4876 
4877 	zend_ast_destroy(ast);
4878 	zend_arena_destroy(ast_arena);
4879 
4880 	return SUCCESS;
4881 }
4882 
try_parse_string(const char * str,size_t len,char quote)4883 static zend_string *try_parse_string(const char *str, size_t len, char quote) {
4884 	if (len == 0) {
4885 		return ZSTR_EMPTY_ALLOC();
4886 	}
4887 
4888 	for (size_t i = 0; i < len; i++) {
4889 		if (str[i] == '\\' || str[i] == quote) {
4890 			return NULL;
4891 		}
4892 	}
4893 	return zend_string_init(str, len, 0);
4894 }
4895 
zend_get_default_from_internal_arg_info(zval * default_value_zval,zend_internal_arg_info * arg_info)4896 ZEND_API zend_result zend_get_default_from_internal_arg_info(
4897 		zval *default_value_zval, zend_internal_arg_info *arg_info)
4898 {
4899 	const char *default_value = arg_info->default_value;
4900 	if (!default_value) {
4901 		return FAILURE;
4902 	}
4903 
4904 	/* Avoid going through the full AST machinery for some simple and common cases. */
4905 	size_t default_value_len = strlen(default_value);
4906 	zend_ulong lval;
4907 	if (default_value_len == sizeof("null")-1
4908 			&& !memcmp(default_value, "null", sizeof("null")-1)) {
4909 		ZVAL_NULL(default_value_zval);
4910 		return SUCCESS;
4911 	} else if (default_value_len == sizeof("true")-1
4912 			&& !memcmp(default_value, "true", sizeof("true")-1)) {
4913 		ZVAL_TRUE(default_value_zval);
4914 		return SUCCESS;
4915 	} else if (default_value_len == sizeof("false")-1
4916 			&& !memcmp(default_value, "false", sizeof("false")-1)) {
4917 		ZVAL_FALSE(default_value_zval);
4918 		return SUCCESS;
4919 	} else if (default_value_len >= 2
4920 			&& (default_value[0] == '\'' || default_value[0] == '"')
4921 			&& default_value[default_value_len - 1] == default_value[0]) {
4922 		zend_string *str = try_parse_string(
4923 			default_value + 1, default_value_len - 2, default_value[0]);
4924 		if (str) {
4925 			ZVAL_STR(default_value_zval, str);
4926 			return SUCCESS;
4927 		}
4928 	} else if (default_value_len == sizeof("[]")-1
4929 			&& !memcmp(default_value, "[]", sizeof("[]")-1)) {
4930 		ZVAL_EMPTY_ARRAY(default_value_zval);
4931 		return SUCCESS;
4932 	} else if (ZEND_HANDLE_NUMERIC_STR(default_value, default_value_len, lval)) {
4933 		ZVAL_LONG(default_value_zval, lval);
4934 		return SUCCESS;
4935 	}
4936 
4937 #if 0
4938 	fprintf(stderr, "Evaluating %s via AST\n", default_value);
4939 #endif
4940 	return get_default_via_ast(default_value_zval, default_value);
4941 }
4942