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 static ZEND_COLD void ZEND_FASTCALL zend_argument_error_variadic(zend_class_entry *error_ce, uint32_t arg_num, const char *format, va_list va) /* {{{ */
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**)malloc(
2275 	    sizeof(zend_module_entry*) *
2276 		(startup_count + 1 +
2277 		 shutdown_count + 1 +
2278 		 post_deactivate_count + 1));
2279 	module_request_startup_handlers[startup_count] = NULL;
2280 	module_request_shutdown_handlers = module_request_startup_handlers + startup_count + 1;
2281 	module_request_shutdown_handlers[shutdown_count] = NULL;
2282 	module_post_deactivate_handlers = module_request_shutdown_handlers + shutdown_count + 1;
2283 	module_post_deactivate_handlers[post_deactivate_count] = NULL;
2284 	startup_count = 0;
2285 
2286 	ZEND_HASH_FOREACH_PTR(&module_registry, module) {
2287 		if (module->request_startup_func) {
2288 			module_request_startup_handlers[startup_count++] = module;
2289 		}
2290 		if (module->request_shutdown_func) {
2291 			module_request_shutdown_handlers[--shutdown_count] = module;
2292 		}
2293 		if (module->post_deactivate_func) {
2294 			module_post_deactivate_handlers[--post_deactivate_count] = module;
2295 		}
2296 	} ZEND_HASH_FOREACH_END();
2297 
2298 	/* Collect internal classes with static members */
2299 	ZEND_HASH_FOREACH_PTR(CG(class_table), ce) {
2300 		if (ce->type == ZEND_INTERNAL_CLASS &&
2301 		    ce->default_static_members_count > 0) {
2302 		    class_count++;
2303 		}
2304 	} ZEND_HASH_FOREACH_END();
2305 
2306 	class_cleanup_handlers = (zend_class_entry**)malloc(
2307 		sizeof(zend_class_entry*) *
2308 		(class_count + 1));
2309 	class_cleanup_handlers[class_count] = NULL;
2310 
2311 	if (class_count) {
2312 		ZEND_HASH_FOREACH_PTR(CG(class_table), ce) {
2313 			if (ce->type == ZEND_INTERNAL_CLASS &&
2314 			    ce->default_static_members_count > 0) {
2315 			    class_cleanup_handlers[--class_count] = ce;
2316 			}
2317 		} ZEND_HASH_FOREACH_END();
2318 	}
2319 }
2320 /* }}} */
2321 
zend_startup_modules(void)2322 ZEND_API void zend_startup_modules(void) /* {{{ */
2323 {
2324 	zend_hash_sort_ex(&module_registry, zend_sort_modules, NULL, 0);
2325 	zend_hash_apply(&module_registry, zend_startup_module_zval);
2326 }
2327 /* }}} */
2328 
zend_destroy_modules(void)2329 ZEND_API void zend_destroy_modules(void) /* {{{ */
2330 {
2331 	free(class_cleanup_handlers);
2332 	free(module_request_startup_handlers);
2333 	zend_hash_graceful_reverse_destroy(&module_registry);
2334 }
2335 /* }}} */
2336 
zend_register_module_ex(zend_module_entry * module)2337 ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module) /* {{{ */
2338 {
2339 	size_t name_len;
2340 	zend_string *lcname;
2341 	zend_module_entry *module_ptr;
2342 
2343 	if (!module) {
2344 		return NULL;
2345 	}
2346 
2347 #if 0
2348 	zend_printf("%s: Registering module %d\n", module->name, module->module_number);
2349 #endif
2350 
2351 	/* Check module dependencies */
2352 	if (module->deps) {
2353 		const zend_module_dep *dep = module->deps;
2354 
2355 		while (dep->name) {
2356 			if (dep->type == MODULE_DEP_CONFLICTS) {
2357 				name_len = strlen(dep->name);
2358 				lcname = zend_string_alloc(name_len, 0);
2359 				zend_str_tolower_copy(ZSTR_VAL(lcname), dep->name, name_len);
2360 
2361 				if (zend_hash_exists(&module_registry, lcname) || zend_get_extension(dep->name)) {
2362 					zend_string_efree(lcname);
2363 					/* TODO: Check version relationship */
2364 					zend_error(E_CORE_WARNING, "Cannot load module \"%s\" because conflicting module \"%s\" is already loaded", module->name, dep->name);
2365 					return NULL;
2366 				}
2367 				zend_string_efree(lcname);
2368 			}
2369 			++dep;
2370 		}
2371 	}
2372 
2373 	name_len = strlen(module->name);
2374 	lcname = zend_string_alloc(name_len, module->type == MODULE_PERSISTENT);
2375 	zend_str_tolower_copy(ZSTR_VAL(lcname), module->name, name_len);
2376 
2377 	lcname = zend_new_interned_string(lcname);
2378 	if ((module_ptr = zend_hash_add_mem(&module_registry, lcname, module, sizeof(zend_module_entry))) == NULL) {
2379 		zend_error(E_CORE_WARNING, "Module \"%s\" is already loaded", module->name);
2380 		zend_string_release(lcname);
2381 		return NULL;
2382 	}
2383 	module = module_ptr;
2384 	EG(current_module) = module;
2385 
2386 	if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type)==FAILURE) {
2387 		zend_hash_del(&module_registry, lcname);
2388 		zend_string_release(lcname);
2389 		EG(current_module) = NULL;
2390 		zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name);
2391 		return NULL;
2392 	}
2393 
2394 	EG(current_module) = NULL;
2395 	zend_string_release(lcname);
2396 	return module;
2397 }
2398 /* }}} */
2399 
zend_register_internal_module(zend_module_entry * module)2400 ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *module) /* {{{ */
2401 {
2402 	module->module_number = zend_next_free_module();
2403 	module->type = MODULE_PERSISTENT;
2404 	return zend_register_module_ex(module);
2405 }
2406 /* }}} */
2407 
zend_check_magic_method_args(uint32_t num_args,const zend_class_entry * ce,const zend_function * fptr,int error_type)2408 static void zend_check_magic_method_args(
2409 		uint32_t num_args, const zend_class_entry *ce, const zend_function *fptr, int error_type)
2410 {
2411 	if (fptr->common.num_args != num_args) {
2412 		if (num_args == 0) {
2413 			zend_error(error_type, "Method %s::%s() cannot take arguments",
2414 				ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2415 		} else if (num_args == 1) {
2416 			zend_error(error_type, "Method %s::%s() must take exactly 1 argument",
2417 				ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2418 		} else {
2419 			zend_error(error_type, "Method %s::%s() must take exactly %" PRIu32 " arguments",
2420 				ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name), num_args);
2421 		}
2422 		return;
2423 	}
2424 	for (uint32_t i = 0; i < num_args; i++) {
2425 		if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, i + 1)) {
2426 			zend_error(error_type, "Method %s::%s() cannot take arguments by reference",
2427 				ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2428 			return;
2429 		}
2430 	}
2431 }
2432 
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)2433 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)
2434 {
2435 		if (
2436 			ZEND_TYPE_IS_SET(fptr->common.arg_info[arg_num].type)
2437 			 && !(ZEND_TYPE_FULL_MASK(fptr->common.arg_info[arg_num].type) & arg_type)
2438 		) {
2439 			zend_error(error_type, "%s::%s(): Parameter #%d ($%s) must be of type %s when declared",
2440 				ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name),
2441 				arg_num + 1, ZSTR_VAL(fptr->common.arg_info[arg_num].name),
2442 				ZSTR_VAL(zend_type_to_string((zend_type) ZEND_TYPE_INIT_MASK(arg_type))));
2443 		}
2444 }
2445 
zend_check_magic_method_return_type(const zend_class_entry * ce,const zend_function * fptr,int error_type,int return_type)2446 static void zend_check_magic_method_return_type(const zend_class_entry *ce, const zend_function *fptr, int error_type, int return_type)
2447 {
2448 	if (!(fptr->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
2449 		/* For backwards compatibility reasons, do not enforce the return type if it is not set. */
2450 		return;
2451 	}
2452 
2453 	if (ZEND_TYPE_PURE_MASK(fptr->common.arg_info[-1].type) & MAY_BE_NEVER) {
2454 		/* It is always legal to specify the never type. */
2455 		return;
2456 	}
2457 
2458 	bool is_complex_type = ZEND_TYPE_IS_COMPLEX(fptr->common.arg_info[-1].type);
2459 	uint32_t extra_types = ZEND_TYPE_PURE_MASK(fptr->common.arg_info[-1].type) & ~return_type;
2460 	if (extra_types & MAY_BE_STATIC) {
2461 		extra_types &= ~MAY_BE_STATIC;
2462 		is_complex_type = true;
2463 	}
2464 
2465 	if (extra_types || (is_complex_type && return_type != MAY_BE_OBJECT)) {
2466 		zend_error(error_type, "%s::%s(): Return type must be %s when declared",
2467 			ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name),
2468 			ZSTR_VAL(zend_type_to_string((zend_type) ZEND_TYPE_INIT_MASK(return_type))));
2469 	}
2470 }
2471 
zend_check_magic_method_non_static(const zend_class_entry * ce,const zend_function * fptr,int error_type)2472 static void zend_check_magic_method_non_static(
2473 		const zend_class_entry *ce, const zend_function *fptr, int error_type)
2474 {
2475 	if (fptr->common.fn_flags & ZEND_ACC_STATIC) {
2476 		zend_error(error_type, "Method %s::%s() cannot be static",
2477 			ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2478 	}
2479 }
2480 
zend_check_magic_method_static(const zend_class_entry * ce,const zend_function * fptr,int error_type)2481 static void zend_check_magic_method_static(
2482 		const zend_class_entry *ce, const zend_function *fptr, int error_type)
2483 {
2484 	if (!(fptr->common.fn_flags & ZEND_ACC_STATIC)) {
2485 		zend_error(error_type, "Method %s::%s() must be static",
2486 			ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2487 	}
2488 }
2489 
zend_check_magic_method_public(const zend_class_entry * ce,const zend_function * fptr,int error_type)2490 static void zend_check_magic_method_public(
2491 		const zend_class_entry *ce, const zend_function *fptr, int error_type)
2492 {
2493 	// TODO: Remove this warning after adding proper visibility handling.
2494 	if (!(fptr->common.fn_flags & ZEND_ACC_PUBLIC)) {
2495 		zend_error(E_WARNING, "The magic method %s::%s() must have public visibility",
2496 			ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2497 	}
2498 }
2499 
zend_check_magic_method_no_return_type(const zend_class_entry * ce,const zend_function * fptr,int error_type)2500 static void zend_check_magic_method_no_return_type(
2501 		const zend_class_entry *ce, const zend_function *fptr, int error_type)
2502 {
2503 	if (fptr->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
2504 		zend_error_noreturn(error_type, "Method %s::%s() cannot declare a return type",
2505 			ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2506 	}
2507 }
2508 
zend_check_magic_method_implementation(const zend_class_entry * ce,const zend_function * fptr,zend_string * lcname,int error_type)2509 ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, zend_string *lcname, int error_type) /* {{{ */
2510 {
2511 	if (ZSTR_VAL(fptr->common.function_name)[0] != '_'
2512 	 || ZSTR_VAL(fptr->common.function_name)[1] != '_') {
2513 		return;
2514 	}
2515 
2516 	if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
2517 		zend_check_magic_method_non_static(ce, fptr, error_type);
2518 		zend_check_magic_method_no_return_type(ce, fptr, error_type);
2519 	} else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) {
2520 		zend_check_magic_method_args(0, ce, fptr, error_type);
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_CLONE_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_return_type(ce, fptr, error_type, MAY_BE_VOID);
2527 	} else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) {
2528 		zend_check_magic_method_args(1, ce, fptr, error_type);
2529 		zend_check_magic_method_non_static(ce, fptr, error_type);
2530 		zend_check_magic_method_public(ce, fptr, error_type);
2531 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2532 	} else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) {
2533 		zend_check_magic_method_args(2, ce, fptr, error_type);
2534 		zend_check_magic_method_non_static(ce, fptr, error_type);
2535 		zend_check_magic_method_public(ce, fptr, error_type);
2536 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2537 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
2538 	} else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) {
2539 		zend_check_magic_method_args(1, ce, fptr, error_type);
2540 		zend_check_magic_method_non_static(ce, fptr, error_type);
2541 		zend_check_magic_method_public(ce, fptr, error_type);
2542 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2543 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
2544 	} else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
2545 		zend_check_magic_method_args(1, ce, fptr, error_type);
2546 		zend_check_magic_method_non_static(ce, fptr, error_type);
2547 		zend_check_magic_method_public(ce, fptr, error_type);
2548 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2549 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_BOOL);
2550 	} else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
2551 		zend_check_magic_method_args(2, ce, fptr, error_type);
2552 		zend_check_magic_method_non_static(ce, fptr, error_type);
2553 		zend_check_magic_method_public(ce, fptr, error_type);
2554 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2555 		zend_check_magic_method_arg_type(1, ce, fptr, error_type, MAY_BE_ARRAY);
2556 	} else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) {
2557 		zend_check_magic_method_args(2, ce, fptr, error_type);
2558 		zend_check_magic_method_static(ce, fptr, error_type);
2559 		zend_check_magic_method_public(ce, fptr, error_type);
2560 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2561 		zend_check_magic_method_arg_type(1, ce, fptr, error_type, MAY_BE_ARRAY);
2562 	} else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
2563 		zend_check_magic_method_args(0, ce, fptr, error_type);
2564 		zend_check_magic_method_non_static(ce, fptr, error_type);
2565 		zend_check_magic_method_public(ce, fptr, error_type);
2566 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_STRING);
2567 	} else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
2568 		zend_check_magic_method_args(0, ce, fptr, error_type);
2569 		zend_check_magic_method_non_static(ce, fptr, error_type);
2570 		zend_check_magic_method_public(ce, fptr, error_type);
2571 		zend_check_magic_method_return_type(ce, fptr, error_type, (MAY_BE_ARRAY | MAY_BE_NULL));
2572 	} else if (zend_string_equals_literal(lcname, "__serialize")) {
2573 		zend_check_magic_method_args(0, ce, fptr, error_type);
2574 		zend_check_magic_method_non_static(ce, fptr, error_type);
2575 		zend_check_magic_method_public(ce, fptr, error_type);
2576 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_ARRAY);
2577 	} else if (zend_string_equals_literal(lcname, "__unserialize")) {
2578 		zend_check_magic_method_args(1, ce, fptr, error_type);
2579 		zend_check_magic_method_non_static(ce, fptr, error_type);
2580 		zend_check_magic_method_public(ce, fptr, error_type);
2581 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_ARRAY);
2582 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
2583 	} else if (zend_string_equals_literal(lcname, "__set_state")) {
2584 		zend_check_magic_method_args(1, ce, fptr, error_type);
2585 		zend_check_magic_method_static(ce, fptr, error_type);
2586 		zend_check_magic_method_public(ce, fptr, error_type);
2587 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_ARRAY);
2588 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_OBJECT);
2589 	} else if (zend_string_equals_literal(lcname, "__invoke")) {
2590 		zend_check_magic_method_non_static(ce, fptr, error_type);
2591 		zend_check_magic_method_public(ce, fptr, error_type);
2592 	} else if (zend_string_equals_literal(lcname, "__sleep")) {
2593 		zend_check_magic_method_args(0, ce, fptr, error_type);
2594 		zend_check_magic_method_non_static(ce, fptr, error_type);
2595 		zend_check_magic_method_public(ce, fptr, error_type);
2596 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_ARRAY);
2597 	} else if (zend_string_equals_literal(lcname, "__wakeup")) {
2598 		zend_check_magic_method_args(0, ce, fptr, error_type);
2599 		zend_check_magic_method_non_static(ce, fptr, error_type);
2600 		zend_check_magic_method_public(ce, fptr, error_type);
2601 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
2602 	}
2603 }
2604 /* }}} */
2605 
zend_add_magic_method(zend_class_entry * ce,zend_function * fptr,zend_string * lcname)2606 ZEND_API void zend_add_magic_method(zend_class_entry *ce, zend_function *fptr, zend_string *lcname)
2607 {
2608 	if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') {
2609 		/* pass */
2610 	} else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) {
2611 		ce->clone = fptr;
2612 	} else if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
2613 		ce->constructor = fptr;
2614 		ce->constructor->common.fn_flags |= ZEND_ACC_CTOR;
2615 	} else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) {
2616 		ce->destructor = fptr;
2617 	} else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) {
2618 		ce->__get = fptr;
2619 		ce->ce_flags |= ZEND_ACC_USE_GUARDS;
2620 	} else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) {
2621 		ce->__set = fptr;
2622 		ce->ce_flags |= ZEND_ACC_USE_GUARDS;
2623 	} else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
2624 		ce->__call = fptr;
2625 	} else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) {
2626 		ce->__unset = fptr;
2627 		ce->ce_flags |= ZEND_ACC_USE_GUARDS;
2628 	} else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
2629 		ce->__isset = fptr;
2630 		ce->ce_flags |= ZEND_ACC_USE_GUARDS;
2631 	} else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) {
2632 		ce->__callstatic = fptr;
2633 	} else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
2634 		ce->__tostring = fptr;
2635 	} else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
2636 		ce->__debugInfo = fptr;
2637 	} else if (zend_string_equals_literal(lcname, "__serialize")) {
2638 		ce->__serialize = fptr;
2639 	} else if (zend_string_equals_literal(lcname, "__unserialize")) {
2640 		ce->__unserialize = fptr;
2641 	}
2642 }
2643 
2644 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arg_info_toString, 0, 0, IS_STRING, 0)
ZEND_END_ARG_INFO()2645 ZEND_END_ARG_INFO()
2646 
2647 /* registers all functions in *library_functions in the function hash */
2648 ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type) /* {{{ */
2649 {
2650 	const zend_function_entry *ptr = functions;
2651 	zend_function function, *reg_function;
2652 	zend_internal_function *internal_function = (zend_internal_function *)&function;
2653 	int count=0, unload=0;
2654 	HashTable *target_function_table = function_table;
2655 	int error_type;
2656 	zend_string *lowercase_name;
2657 	size_t fname_len;
2658 
2659 	if (type==MODULE_PERSISTENT) {
2660 		error_type = E_CORE_WARNING;
2661 	} else {
2662 		error_type = E_WARNING;
2663 	}
2664 
2665 	if (!target_function_table) {
2666 		target_function_table = CG(function_table);
2667 	}
2668 	internal_function->type = ZEND_INTERNAL_FUNCTION;
2669 	internal_function->module = EG(current_module);
2670 	memset(internal_function->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
2671 
2672 	while (ptr->fname) {
2673 		fname_len = strlen(ptr->fname);
2674 		internal_function->handler = ptr->handler;
2675 		internal_function->function_name = zend_string_init_interned(ptr->fname, fname_len, 1);
2676 		internal_function->scope = scope;
2677 		internal_function->prototype = NULL;
2678 		internal_function->attributes = NULL;
2679 		if (ptr->flags) {
2680 			if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
2681 				if (ptr->flags != ZEND_ACC_DEPRECATED && scope) {
2682 					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);
2683 				}
2684 				internal_function->fn_flags = ZEND_ACC_PUBLIC | ptr->flags;
2685 			} else {
2686 				internal_function->fn_flags = ptr->flags;
2687 			}
2688 		} else {
2689 			internal_function->fn_flags = ZEND_ACC_PUBLIC;
2690 		}
2691 
2692 		if (ptr->arg_info) {
2693 			zend_internal_function_info *info = (zend_internal_function_info*)ptr->arg_info;
2694 			internal_function->arg_info = (zend_internal_arg_info*)ptr->arg_info+1;
2695 			internal_function->num_args = ptr->num_args;
2696 			/* Currently you cannot denote that the function can accept less arguments than num_args */
2697 			if (info->required_num_args == (zend_uintptr_t)-1) {
2698 				internal_function->required_num_args = ptr->num_args;
2699 			} else {
2700 				internal_function->required_num_args = info->required_num_args;
2701 			}
2702 			if (ZEND_ARG_SEND_MODE(info)) {
2703 				internal_function->fn_flags |= ZEND_ACC_RETURN_REFERENCE;
2704 			}
2705 			if (ZEND_ARG_IS_VARIADIC(&ptr->arg_info[ptr->num_args])) {
2706 				internal_function->fn_flags |= ZEND_ACC_VARIADIC;
2707 				/* Don't count the variadic argument */
2708 				internal_function->num_args--;
2709 			}
2710 			if (ZEND_TYPE_IS_SET(info->type)) {
2711 				if (ZEND_TYPE_HAS_NAME(info->type)) {
2712 					const char *type_name = ZEND_TYPE_LITERAL_NAME(info->type);
2713 					if (!scope && (!strcasecmp(type_name, "self") || !strcasecmp(type_name, "parent"))) {
2714 						zend_error_noreturn(E_CORE_ERROR, "Cannot declare a return type of %s outside of a class scope", type_name);
2715 					}
2716 				}
2717 
2718 				internal_function->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
2719 			}
2720 		} else {
2721 			zend_error(E_CORE_WARNING, "Missing arginfo for %s%s%s()",
2722 				 scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2723 
2724 			internal_function->arg_info = NULL;
2725 			internal_function->num_args = 0;
2726 			internal_function->required_num_args = 0;
2727 		}
2728 
2729 		/* If not specified, add __toString() return type for compatibility with Stringable
2730 		 * interface. */
2731 		if (scope && zend_string_equals_literal_ci(internal_function->function_name, "__tostring") &&
2732 				!(internal_function->fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
2733 			internal_function->arg_info = (zend_internal_arg_info *) arg_info_toString + 1;
2734 			internal_function->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
2735 			internal_function->num_args = internal_function->required_num_args = 0;
2736 		}
2737 
2738 
2739 		zend_set_function_arg_flags((zend_function*)internal_function);
2740 		if (ptr->flags & ZEND_ACC_ABSTRACT) {
2741 			if (scope) {
2742 				/* This is a class that must be abstract itself. Here we set the check info. */
2743 				scope->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
2744 				if (!(scope->ce_flags & ZEND_ACC_INTERFACE)) {
2745 					/* Since the class is not an interface it needs to be declared as a abstract class. */
2746 					/* Since here we are handling internal functions only we can add the keyword flag. */
2747 					/* This time we set the flag for the keyword 'abstract'. */
2748 					scope->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
2749 				}
2750 			}
2751 			if ((ptr->flags & ZEND_ACC_STATIC) && (!scope || !(scope->ce_flags & ZEND_ACC_INTERFACE))) {
2752 				zend_error(error_type, "Static function %s%s%s() cannot be abstract", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2753 			}
2754 		} else {
2755 			if (scope && (scope->ce_flags & ZEND_ACC_INTERFACE)) {
2756 				zend_error(error_type, "Interface %s cannot contain non abstract method %s()", ZSTR_VAL(scope->name), ptr->fname);
2757 				return FAILURE;
2758 			}
2759 			if (!internal_function->handler) {
2760 				zend_error(error_type, "Method %s%s%s() cannot be a NULL function", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2761 				zend_unregister_functions(functions, count, target_function_table);
2762 				return FAILURE;
2763 			}
2764 		}
2765 		lowercase_name = zend_string_tolower_ex(internal_function->function_name, type == MODULE_PERSISTENT);
2766 		lowercase_name = zend_new_interned_string(lowercase_name);
2767 		reg_function = malloc(sizeof(zend_internal_function));
2768 		memcpy(reg_function, &function, sizeof(zend_internal_function));
2769 		if (zend_hash_add_ptr(target_function_table, lowercase_name, reg_function) == NULL) {
2770 			unload=1;
2771 			free(reg_function);
2772 			zend_string_release(lowercase_name);
2773 			break;
2774 		}
2775 
2776 		/* Get parameter count including variadic parameter. */
2777 		uint32_t num_args = reg_function->common.num_args;
2778 		if (reg_function->common.fn_flags & ZEND_ACC_VARIADIC) {
2779 			num_args++;
2780 		}
2781 
2782 		/* If types of arguments have to be checked */
2783 		if (reg_function->common.arg_info && num_args) {
2784 			uint32_t i;
2785 			for (i = 0; i < num_args; i++) {
2786 				zend_internal_arg_info *arg_info = &reg_function->internal_function.arg_info[i];
2787 				ZEND_ASSERT(arg_info->name && "Parameter must have a name");
2788 				if (ZEND_TYPE_IS_SET(arg_info->type)) {
2789 				    reg_function->common.fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
2790 				}
2791 #if ZEND_DEBUG
2792 				for (uint32_t j = 0; j < i; j++) {
2793 					if (!strcmp(arg_info->name, reg_function->internal_function.arg_info[j].name)) {
2794 						zend_error_noreturn(E_CORE_ERROR,
2795 							"Duplicate parameter name $%s for function %s%s%s()", arg_info->name,
2796 							scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2797 					}
2798 				}
2799 #endif
2800 			}
2801 		}
2802 
2803 		if (reg_function->common.arg_info &&
2804 		    (reg_function->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS))) {
2805 			/* convert "const char*" class type names into "zend_string*" */
2806 			uint32_t i;
2807 			zend_arg_info *arg_info = reg_function->common.arg_info - 1;
2808 			zend_arg_info *new_arg_info;
2809 
2810 			/* Treat return type as an extra argument */
2811 			num_args++;
2812 			new_arg_info = malloc(sizeof(zend_arg_info) * num_args);
2813 			memcpy(new_arg_info, arg_info, sizeof(zend_arg_info) * num_args);
2814 			reg_function->common.arg_info = new_arg_info + 1;
2815 			for (i = 0; i < num_args; i++) {
2816 				if (ZEND_TYPE_IS_COMPLEX(new_arg_info[i].type)) {
2817 					ZEND_ASSERT(ZEND_TYPE_HAS_NAME(new_arg_info[i].type)
2818 						&& "Should be stored as simple name");
2819 					const char *class_name = ZEND_TYPE_LITERAL_NAME(new_arg_info[i].type);
2820 
2821 					size_t num_types = 1;
2822 					const char *p = class_name;
2823 					while ((p = strchr(p, '|'))) {
2824 						num_types++;
2825 						p++;
2826 					}
2827 
2828 					if (num_types == 1) {
2829 						/* Simple class type */
2830 						ZEND_TYPE_SET_PTR(new_arg_info[i].type,
2831 							zend_string_init_interned(class_name, strlen(class_name), 1));
2832 					} else {
2833 						/* Union type */
2834 						zend_type_list *list = malloc(ZEND_TYPE_LIST_SIZE(num_types));
2835 						list->num_types = num_types;
2836 						ZEND_TYPE_SET_LIST(new_arg_info[i].type, list);
2837 						ZEND_TYPE_FULL_MASK(new_arg_info[i].type) |= _ZEND_TYPE_UNION_BIT;
2838 
2839 						const char *start = class_name;
2840 						uint32_t j = 0;
2841 						while (true) {
2842 							const char *end = strchr(start, '|');
2843 							zend_string *str = zend_string_init_interned(
2844 								start, end ? end - start : strlen(start), 1);
2845 							list->types[j] = (zend_type) ZEND_TYPE_INIT_CLASS(str, 0, 0);
2846 							if (!end) {
2847 								break;
2848 							}
2849 							start = end + 1;
2850 							j++;
2851 						}
2852 					}
2853 				}
2854 			}
2855 		}
2856 
2857 		if (scope) {
2858 			zend_check_magic_method_implementation(
2859 				scope, reg_function, lowercase_name, E_CORE_ERROR);
2860 			zend_add_magic_method(scope, reg_function, lowercase_name);
2861 		}
2862 		ptr++;
2863 		count++;
2864 		zend_string_release(lowercase_name);
2865 	}
2866 	if (unload) { /* before unloading, display all remaining bad function in the module */
2867 		while (ptr->fname) {
2868 			fname_len = strlen(ptr->fname);
2869 			lowercase_name = zend_string_alloc(fname_len, 0);
2870 			zend_str_tolower_copy(ZSTR_VAL(lowercase_name), ptr->fname, fname_len);
2871 			if (zend_hash_exists(target_function_table, lowercase_name)) {
2872 				zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2873 			}
2874 			zend_string_efree(lowercase_name);
2875 			ptr++;
2876 		}
2877 		zend_unregister_functions(functions, count, target_function_table);
2878 		return FAILURE;
2879 	}
2880 	return SUCCESS;
2881 }
2882 /* }}} */
2883 
2884 /* count=-1 means erase all functions, otherwise,
2885  * erase the first count functions
2886  */
zend_unregister_functions(const zend_function_entry * functions,int count,HashTable * function_table)2887 ZEND_API void zend_unregister_functions(const zend_function_entry *functions, int count, HashTable *function_table) /* {{{ */
2888 {
2889 	const zend_function_entry *ptr = functions;
2890 	int i=0;
2891 	HashTable *target_function_table = function_table;
2892 	zend_string *lowercase_name;
2893 	size_t fname_len;
2894 
2895 	if (!target_function_table) {
2896 		target_function_table = CG(function_table);
2897 	}
2898 	while (ptr->fname) {
2899 		if (count!=-1 && i>=count) {
2900 			break;
2901 		}
2902 		fname_len = strlen(ptr->fname);
2903 		lowercase_name = zend_string_alloc(fname_len, 0);
2904 		zend_str_tolower_copy(ZSTR_VAL(lowercase_name), ptr->fname, fname_len);
2905 		zend_hash_del(target_function_table, lowercase_name);
2906 		zend_string_efree(lowercase_name);
2907 		ptr++;
2908 		i++;
2909 	}
2910 }
2911 /* }}} */
2912 
zend_startup_module(zend_module_entry * module)2913 ZEND_API zend_result zend_startup_module(zend_module_entry *module) /* {{{ */
2914 {
2915 	if ((module = zend_register_internal_module(module)) != NULL && zend_startup_module_ex(module) == SUCCESS) {
2916 		return SUCCESS;
2917 	}
2918 	return FAILURE;
2919 }
2920 /* }}} */
2921 
zend_get_module_started(const char * module_name)2922 ZEND_API zend_result zend_get_module_started(const char *module_name) /* {{{ */
2923 {
2924 	zend_module_entry *module;
2925 
2926 	module = zend_hash_str_find_ptr(&module_registry, module_name, strlen(module_name));
2927 	return (module && module->module_started) ? SUCCESS : FAILURE;
2928 }
2929 /* }}} */
2930 
clean_module_class(zval * el,void * arg)2931 static int clean_module_class(zval *el, void *arg) /* {{{ */
2932 {
2933 	zend_class_entry *ce = (zend_class_entry *)Z_PTR_P(el);
2934 	int module_number = *(int *)arg;
2935 	if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module->module_number == module_number) {
2936 		return ZEND_HASH_APPLY_REMOVE;
2937 	} else {
2938 		return ZEND_HASH_APPLY_KEEP;
2939 	}
2940 }
2941 /* }}} */
2942 
clean_module_classes(int module_number)2943 static void clean_module_classes(int module_number) /* {{{ */
2944 {
2945 	zend_hash_apply_with_argument(EG(class_table), clean_module_class, (void *) &module_number);
2946 }
2947 /* }}} */
2948 
module_destructor(zend_module_entry * module)2949 void module_destructor(zend_module_entry *module) /* {{{ */
2950 {
2951 
2952 	if (module->type == MODULE_TEMPORARY) {
2953 		zend_clean_module_rsrc_dtors(module->module_number);
2954 		clean_module_constants(module->module_number);
2955 		clean_module_classes(module->module_number);
2956 	}
2957 
2958 	if (module->module_started && module->module_shutdown_func) {
2959 #if 0
2960 		zend_printf("%s: Module shutdown\n", module->name);
2961 #endif
2962 		module->module_shutdown_func(module->type, module->module_number);
2963 	}
2964 
2965 	if (module->module_started
2966 	 && !module->module_shutdown_func
2967 	 && module->type == MODULE_TEMPORARY) {
2968 		zend_unregister_ini_entries(module->module_number);
2969 	}
2970 
2971 	/* Deinitialize module globals */
2972 	if (module->globals_size) {
2973 #ifdef ZTS
2974 		if (*module->globals_id_ptr) {
2975 			ts_free_id(*module->globals_id_ptr);
2976 		}
2977 #else
2978 		if (module->globals_dtor) {
2979 			module->globals_dtor(module->globals_ptr);
2980 		}
2981 #endif
2982 	}
2983 
2984 	module->module_started=0;
2985 	if (module->type == MODULE_TEMPORARY && module->functions) {
2986 		zend_unregister_functions(module->functions, -1, NULL);
2987 	}
2988 
2989 #if HAVE_LIBDL
2990 	if (module->handle && !getenv("ZEND_DONT_UNLOAD_MODULES")) {
2991 		DL_UNLOAD(module->handle);
2992 	}
2993 #endif
2994 }
2995 /* }}} */
2996 
zend_activate_modules(void)2997 ZEND_API void zend_activate_modules(void) /* {{{ */
2998 {
2999 	zend_module_entry **p = module_request_startup_handlers;
3000 
3001 	while (*p) {
3002 		zend_module_entry *module = *p;
3003 
3004 		if (module->request_startup_func(module->type, module->module_number)==FAILURE) {
3005 			zend_error(E_WARNING, "request_startup() for %s module failed", module->name);
3006 			exit(1);
3007 		}
3008 		p++;
3009 	}
3010 }
3011 /* }}} */
3012 
zend_deactivate_modules(void)3013 ZEND_API void zend_deactivate_modules(void) /* {{{ */
3014 {
3015 	EG(current_execute_data) = NULL; /* we're no longer executing anything */
3016 
3017 	if (EG(full_tables_cleanup)) {
3018 		zend_module_entry *module;
3019 
3020 		ZEND_HASH_REVERSE_FOREACH_PTR(&module_registry, module) {
3021 			if (module->request_shutdown_func) {
3022 				zend_try {
3023 					module->request_shutdown_func(module->type, module->module_number);
3024 				} zend_end_try();
3025 			}
3026 		} ZEND_HASH_FOREACH_END();
3027 	} else {
3028 		zend_module_entry **p = module_request_shutdown_handlers;
3029 
3030 		while (*p) {
3031 			zend_module_entry *module = *p;
3032 			zend_try {
3033 				module->request_shutdown_func(module->type, module->module_number);
3034 			} zend_end_try();
3035 			p++;
3036 		}
3037 	}
3038 }
3039 /* }}} */
3040 
zend_post_deactivate_modules(void)3041 ZEND_API void zend_post_deactivate_modules(void) /* {{{ */
3042 {
3043 	if (EG(full_tables_cleanup)) {
3044 		zend_module_entry *module;
3045 		zval *zv;
3046 		zend_string *key;
3047 
3048 		ZEND_HASH_FOREACH_PTR(&module_registry, module) {
3049 			if (module->post_deactivate_func) {
3050 				module->post_deactivate_func();
3051 			}
3052 		} ZEND_HASH_FOREACH_END();
3053 		ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(&module_registry, key, zv) {
3054 			module = Z_PTR_P(zv);
3055 			if (module->type != MODULE_TEMPORARY) {
3056 				break;
3057 			}
3058 			module_destructor(module);
3059 			free(module);
3060 			zend_string_release_ex(key, 0);
3061 		} ZEND_HASH_FOREACH_END_DEL();
3062 	} else {
3063 		zend_module_entry **p = module_post_deactivate_handlers;
3064 
3065 		while (*p) {
3066 			zend_module_entry *module = *p;
3067 
3068 			module->post_deactivate_func();
3069 			p++;
3070 		}
3071 	}
3072 }
3073 /* }}} */
3074 
3075 /* return the next free module number */
zend_next_free_module(void)3076 ZEND_API int zend_next_free_module(void) /* {{{ */
3077 {
3078 	return zend_hash_num_elements(&module_registry) + 1;
3079 }
3080 /* }}} */
3081 
do_register_internal_class(zend_class_entry * orig_class_entry,uint32_t ce_flags)3082 static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, uint32_t ce_flags) /* {{{ */
3083 {
3084 	zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
3085 	zend_string *lowercase_name;
3086 	*class_entry = *orig_class_entry;
3087 
3088 	class_entry->type = ZEND_INTERNAL_CLASS;
3089 	zend_initialize_class_data(class_entry, 0);
3090 	zend_alloc_ce_cache(class_entry->name);
3091 	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;
3092 	class_entry->info.internal.module = EG(current_module);
3093 
3094 	if (class_entry->info.internal.builtin_functions) {
3095 		zend_register_functions(class_entry, class_entry->info.internal.builtin_functions, &class_entry->function_table, EG(current_module)->type);
3096 	}
3097 
3098 	lowercase_name = zend_string_tolower_ex(orig_class_entry->name, EG(current_module)->type == MODULE_PERSISTENT);
3099 	lowercase_name = zend_new_interned_string(lowercase_name);
3100 	zend_hash_update_ptr(CG(class_table), lowercase_name, class_entry);
3101 	zend_string_release_ex(lowercase_name, 1);
3102 
3103 	if (class_entry->__tostring && !zend_string_equals_literal(class_entry->name, "Stringable")
3104 			&& !(class_entry->ce_flags & ZEND_ACC_TRAIT)) {
3105 		ZEND_ASSERT(zend_ce_stringable
3106 			&& "Should be registered before first class using __toString()");
3107 		zend_do_implement_interface(class_entry, zend_ce_stringable);
3108 	}
3109 	return class_entry;
3110 }
3111 /* }}} */
3112 
3113 /* If parent_ce is not NULL then it inherits from parent_ce
3114  * If parent_ce is NULL and parent_name isn't then it looks for the parent and inherits from it
3115  * If both parent_ce and parent_name are NULL it does a regular class registration
3116  * If parent_name is specified but not found NULL is returned
3117  */
zend_register_internal_class_ex(zend_class_entry * class_entry,zend_class_entry * parent_ce)3118 ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce) /* {{{ */
3119 {
3120 	zend_class_entry *register_class;
3121 
3122 	register_class = zend_register_internal_class(class_entry);
3123 
3124 	if (parent_ce) {
3125 		zend_do_inheritance(register_class, parent_ce);
3126 		zend_build_properties_info_table(register_class);
3127 	}
3128 
3129 	return register_class;
3130 }
3131 /* }}} */
3132 
zend_class_implements(zend_class_entry * class_entry,int num_interfaces,...)3133 ZEND_API void zend_class_implements(zend_class_entry *class_entry, int num_interfaces, ...) /* {{{ */
3134 {
3135 	zend_class_entry *interface_entry;
3136 	va_list interface_list;
3137 	va_start(interface_list, num_interfaces);
3138 
3139 	while (num_interfaces--) {
3140 		interface_entry = va_arg(interface_list, zend_class_entry *);
3141 		if (interface_entry == zend_ce_stringable
3142 				&& zend_class_implements_interface(class_entry, zend_ce_stringable)) {
3143 			/* Stringable is implemented automatically,
3144 			 * silently ignore an explicit implementation. */
3145 			continue;
3146 		}
3147 
3148 		zend_do_implement_interface(class_entry, interface_entry);
3149 	}
3150 
3151 	va_end(interface_list);
3152 }
3153 /* }}} */
3154 
3155 /* A class that contains at least one abstract method automatically becomes an abstract class.
3156  */
zend_register_internal_class(zend_class_entry * orig_class_entry)3157 ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry) /* {{{ */
3158 {
3159 	return do_register_internal_class(orig_class_entry, 0);
3160 }
3161 /* }}} */
3162 
zend_register_internal_interface(zend_class_entry * orig_class_entry)3163 ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry) /* {{{ */
3164 {
3165 	return do_register_internal_class(orig_class_entry, ZEND_ACC_INTERFACE);
3166 }
3167 /* }}} */
3168 
zend_register_class_alias_ex(const char * name,size_t name_len,zend_class_entry * ce,bool persistent)3169 ZEND_API zend_result zend_register_class_alias_ex(const char *name, size_t name_len, zend_class_entry *ce, bool persistent) /* {{{ */
3170 {
3171 	zend_string *lcname;
3172 	zval zv, *ret;
3173 
3174 	/* TODO: Move this out of here in 7.4. */
3175 	if (persistent && EG(current_module) && EG(current_module)->type == MODULE_TEMPORARY) {
3176 		persistent = 0;
3177 	}
3178 
3179 	if (name[0] == '\\') {
3180 		lcname = zend_string_alloc(name_len-1, persistent);
3181 		zend_str_tolower_copy(ZSTR_VAL(lcname), name+1, name_len-1);
3182 	} else {
3183 		lcname = zend_string_alloc(name_len, persistent);
3184 		zend_str_tolower_copy(ZSTR_VAL(lcname), name, name_len);
3185 	}
3186 
3187 	zend_assert_valid_class_name(lcname);
3188 
3189 	lcname = zend_new_interned_string(lcname);
3190 
3191 	ZVAL_ALIAS_PTR(&zv, ce);
3192 	ret = zend_hash_add(CG(class_table), lcname, &zv);
3193 	zend_string_release_ex(lcname, 0);
3194 	if (ret) {
3195 		if (!(ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
3196 			ce->refcount++;
3197 		}
3198 		return SUCCESS;
3199 	}
3200 	return FAILURE;
3201 }
3202 /* }}} */
3203 
3204 // 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,...)3205 ZEND_API zend_result zend_set_hash_symbol(zval *symbol, const char *name, size_t name_length, bool is_ref, int num_symbol_tables, ...) /* {{{ */
3206 {
3207 	HashTable *symbol_table;
3208 	va_list symbol_table_list;
3209 
3210 	if (num_symbol_tables <= 0) return FAILURE;
3211 
3212 	if (is_ref) {
3213 		ZVAL_MAKE_REF(symbol);
3214 	}
3215 
3216 	va_start(symbol_table_list, num_symbol_tables);
3217 	while (num_symbol_tables-- > 0) {
3218 		symbol_table = va_arg(symbol_table_list, HashTable *);
3219 		zend_hash_str_update(symbol_table, name, name_length, symbol);
3220 		Z_TRY_ADDREF_P(symbol);
3221 	}
3222 	va_end(symbol_table_list);
3223 	return SUCCESS;
3224 }
3225 /* }}} */
3226 
3227 /* Disabled functions support */
3228 
zend_disable_function(const char * function_name,size_t function_name_length)3229 static void zend_disable_function(const char *function_name, size_t function_name_length)
3230 {
3231 	zend_hash_str_del(CG(function_table), function_name, function_name_length);
3232 }
3233 
zend_disable_functions(const char * function_list)3234 ZEND_API void zend_disable_functions(const char *function_list) /* {{{ */
3235 {
3236 	if (!function_list || !*function_list) {
3237 		return;
3238 	}
3239 
3240 	const char *s = NULL, *e = function_list;
3241 	while (*e) {
3242 		switch (*e) {
3243 			case ' ':
3244 			case ',':
3245 				if (s) {
3246 					zend_disable_function(s, e - s);
3247 					s = NULL;
3248 				}
3249 				break;
3250 			default:
3251 				if (!s) {
3252 					s = e;
3253 				}
3254 				break;
3255 		}
3256 		e++;
3257 	}
3258 	if (s) {
3259 		zend_disable_function(s, e - s);
3260 	}
3261 
3262 	/* Rehash the function table after deleting functions. This ensures that all internal
3263 	 * functions are contiguous, which means we don't need to perform full table cleanup
3264 	 * on shutdown. */
3265 	zend_hash_rehash(CG(function_table));
3266 }
3267 /* }}} */
3268 
3269 #ifdef ZEND_WIN32
3270 #pragma optimize("", off)
3271 #endif
display_disabled_class(zend_class_entry * class_type)3272 static ZEND_COLD zend_object *display_disabled_class(zend_class_entry *class_type) /* {{{ */
3273 {
3274 	zend_object *intern;
3275 
3276 	intern = zend_objects_new(class_type);
3277 
3278 	/* Initialize default properties */
3279 	if (EXPECTED(class_type->default_properties_count != 0)) {
3280 		zval *p = intern->properties_table;
3281 		zval *end = p + class_type->default_properties_count;
3282 		do {
3283 			ZVAL_UNDEF(p);
3284 			p++;
3285 		} while (p != end);
3286 	}
3287 
3288 	zend_error(E_WARNING, "%s() has been disabled for security reasons", ZSTR_VAL(class_type->name));
3289 	return intern;
3290 }
3291 #ifdef ZEND_WIN32
3292 #pragma optimize("", on)
3293 #endif
3294 /* }}} */
3295 
3296 static const zend_function_entry disabled_class_new[] = {
3297 	ZEND_FE_END
3298 };
3299 
zend_disable_class(const char * class_name,size_t class_name_length)3300 ZEND_API zend_result zend_disable_class(const char *class_name, size_t class_name_length) /* {{{ */
3301 {
3302 	zend_class_entry *disabled_class;
3303 	zend_string *key;
3304 	zend_function *fn;
3305 	zend_property_info *prop;
3306 
3307 	key = zend_string_alloc(class_name_length, 0);
3308 	zend_str_tolower_copy(ZSTR_VAL(key), class_name, class_name_length);
3309 	disabled_class = zend_hash_find_ptr(CG(class_table), key);
3310 	zend_string_release_ex(key, 0);
3311 	if (!disabled_class) {
3312 		return FAILURE;
3313 	}
3314 
3315 	/* Will be reset by INIT_CLASS_ENTRY. */
3316 	free(disabled_class->interfaces);
3317 
3318 	INIT_CLASS_ENTRY_INIT_METHODS((*disabled_class), disabled_class_new);
3319 	disabled_class->create_object = display_disabled_class;
3320 
3321 	ZEND_HASH_FOREACH_PTR(&disabled_class->function_table, fn) {
3322 		if ((fn->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) &&
3323 			fn->common.scope == disabled_class) {
3324 			zend_free_internal_arg_info(&fn->internal_function);
3325 		}
3326 	} ZEND_HASH_FOREACH_END();
3327 	zend_hash_clean(&disabled_class->function_table);
3328 	ZEND_HASH_FOREACH_PTR(&disabled_class->properties_info, prop) {
3329 		if (prop->ce == disabled_class) {
3330 			zend_string_release(prop->name);
3331 			zend_type_release(prop->type, /* persistent */ 1);
3332 			free(prop);
3333 		}
3334 	} ZEND_HASH_FOREACH_END();
3335 	zend_hash_clean(&disabled_class->properties_info);
3336 	return SUCCESS;
3337 }
3338 /* }}} */
3339 
get_scope(zend_execute_data * frame)3340 static zend_always_inline zend_class_entry *get_scope(zend_execute_data *frame)
3341 {
3342 	return frame && frame->func ? frame->func->common.scope : NULL;
3343 }
3344 
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)3345 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) /* {{{ */
3346 {
3347 	bool ret = 0;
3348 	zend_class_entry *ce;
3349 	size_t name_len = ZSTR_LEN(name);
3350 	zend_string *lcname;
3351 	ALLOCA_FLAG(use_heap);
3352 
3353 	ZSTR_ALLOCA_ALLOC(lcname, name_len, use_heap);
3354 	zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(name), name_len);
3355 
3356 	*strict_class = 0;
3357 	if (zend_string_equals_literal(lcname, "self")) {
3358 		if (!scope) {
3359 			if (error) *error = estrdup("cannot access \"self\" when no class scope is active");
3360 		} else {
3361 			fcc->called_scope = zend_get_called_scope(frame);
3362 			if (!fcc->called_scope || !instanceof_function(fcc->called_scope, scope)) {
3363 				fcc->called_scope = scope;
3364 			}
3365 			fcc->calling_scope = scope;
3366 			if (!fcc->object) {
3367 				fcc->object = zend_get_this_object(frame);
3368 			}
3369 			ret = 1;
3370 		}
3371 	} else if (zend_string_equals_literal(lcname, "parent")) {
3372 		if (!scope) {
3373 			if (error) *error = estrdup("cannot access \"parent\" when no class scope is active");
3374 		} else if (!scope->parent) {
3375 			if (error) *error = estrdup("cannot access \"parent\" when current class scope has no parent");
3376 		} else {
3377 			fcc->called_scope = zend_get_called_scope(frame);
3378 			if (!fcc->called_scope || !instanceof_function(fcc->called_scope, scope->parent)) {
3379 				fcc->called_scope = scope->parent;
3380 			}
3381 			fcc->calling_scope = scope->parent;
3382 			if (!fcc->object) {
3383 				fcc->object = zend_get_this_object(frame);
3384 			}
3385 			*strict_class = 1;
3386 			ret = 1;
3387 		}
3388 	} else if (zend_string_equals_literal(lcname, "static")) {
3389 		zend_class_entry *called_scope = zend_get_called_scope(frame);
3390 
3391 		if (!called_scope) {
3392 			if (error) *error = estrdup("cannot access \"static\" when no class scope is active");
3393 		} else {
3394 			fcc->called_scope = called_scope;
3395 			fcc->calling_scope = called_scope;
3396 			if (!fcc->object) {
3397 				fcc->object = zend_get_this_object(frame);
3398 			}
3399 			*strict_class = 1;
3400 			ret = 1;
3401 		}
3402 	} else if ((ce = zend_lookup_class(name)) != NULL) {
3403 		zend_class_entry *scope = get_scope(frame);
3404 		fcc->calling_scope = ce;
3405 		if (scope && !fcc->object) {
3406 			zend_object *object = zend_get_this_object(frame);
3407 
3408 			if (object &&
3409 			    instanceof_function(object->ce, scope) &&
3410 			    instanceof_function(scope, ce)) {
3411 				fcc->object = object;
3412 				fcc->called_scope = object->ce;
3413 			} else {
3414 				fcc->called_scope = ce;
3415 			}
3416 		} else {
3417 			fcc->called_scope = fcc->object ? fcc->object->ce : ce;
3418 		}
3419 		*strict_class = 1;
3420 		ret = 1;
3421 	} else {
3422 		if (error) zend_spprintf(error, 0, "class \"%.*s\" not found", (int)name_len, ZSTR_VAL(name));
3423 	}
3424 	ZSTR_ALLOCA_FREE(lcname, use_heap);
3425 	return ret;
3426 }
3427 /* }}} */
3428 
zend_release_fcall_info_cache(zend_fcall_info_cache * fcc)3429 ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc) {
3430 	if (fcc->function_handler &&
3431 		(fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
3432 		if (fcc->function_handler->common.function_name) {
3433 			zend_string_release_ex(fcc->function_handler->common.function_name, 0);
3434 		}
3435 		zend_free_trampoline(fcc->function_handler);
3436 		fcc->function_handler = NULL;
3437 	}
3438 }
3439 
zend_is_callable_check_func(int check_flags,zval * callable,zend_execute_data * frame,zend_fcall_info_cache * fcc,bool strict_class,char ** error)3440 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) /* {{{ */
3441 {
3442 	zend_class_entry *ce_org = fcc->calling_scope;
3443 	bool retval = 0;
3444 	zend_string *mname, *cname;
3445 	zend_string *lmname;
3446 	const char *colon;
3447 	size_t clen;
3448 	HashTable *ftable;
3449 	int call_via_handler = 0;
3450 	zend_class_entry *scope;
3451 	zval *zv;
3452 	ALLOCA_FLAG(use_heap)
3453 
3454 	fcc->calling_scope = NULL;
3455 
3456 	if (!ce_org) {
3457 		zend_function *func;
3458 		zend_string *lmname;
3459 
3460 		/* Check if function with given name exists.
3461 		 * This may be a compound name that includes namespace name */
3462 		if (UNEXPECTED(Z_STRVAL_P(callable)[0] == '\\')) {
3463 			/* Skip leading \ */
3464 			ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable) - 1, use_heap);
3465 			zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable) + 1, Z_STRLEN_P(callable) - 1);
3466 			func = zend_fetch_function(lmname);
3467 			ZSTR_ALLOCA_FREE(lmname, use_heap);
3468 		} else {
3469 			lmname = Z_STR_P(callable);
3470 			func = zend_fetch_function(lmname);
3471 			if (!func) {
3472 				ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable), use_heap);
3473 				zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable), Z_STRLEN_P(callable));
3474 				func = zend_fetch_function(lmname);
3475 				ZSTR_ALLOCA_FREE(lmname, use_heap);
3476 			}
3477 		}
3478 		if (EXPECTED(func != NULL)) {
3479 			fcc->function_handler = func;
3480 			return 1;
3481 		}
3482 	}
3483 
3484 	/* Split name into class/namespace and method/function names */
3485 	if ((colon = zend_memrchr(Z_STRVAL_P(callable), ':', Z_STRLEN_P(callable))) != NULL &&
3486 		colon > Z_STRVAL_P(callable) &&
3487 		*(colon-1) == ':'
3488 	) {
3489 		size_t mlen;
3490 
3491 		colon--;
3492 		clen = colon - Z_STRVAL_P(callable);
3493 		mlen = Z_STRLEN_P(callable) - clen - 2;
3494 
3495 		if (colon == Z_STRVAL_P(callable)) {
3496 			if (error) *error = estrdup("invalid function name");
3497 			return 0;
3498 		}
3499 
3500 		/* This is a compound name.
3501 		 * Try to fetch class and then find static method. */
3502 		if (ce_org) {
3503 			scope = ce_org;
3504 		} else {
3505 			scope = get_scope(frame);
3506 		}
3507 
3508 		cname = zend_string_init_interned(Z_STRVAL_P(callable), clen, 0);
3509 		if (ZSTR_HAS_CE_CACHE(cname) && ZSTR_GET_CE_CACHE(cname)) {
3510 			fcc->calling_scope = ZSTR_GET_CE_CACHE(cname);
3511 			if (scope && !fcc->object) {
3512 				zend_object *object = zend_get_this_object(frame);
3513 
3514 				if (object &&
3515 				    instanceof_function(object->ce, scope) &&
3516 				    instanceof_function(scope, fcc->calling_scope)) {
3517 					fcc->object = object;
3518 					fcc->called_scope = object->ce;
3519 				} else {
3520 					fcc->called_scope = fcc->calling_scope;
3521 				}
3522 			} else {
3523 				fcc->called_scope = fcc->object ? fcc->object->ce : fcc->calling_scope;
3524 			}
3525 			strict_class = 1;
3526 		} else if (!zend_is_callable_check_class(cname, scope, frame, fcc, &strict_class, error)) {
3527 			zend_string_release_ex(cname, 0);
3528 			return 0;
3529 		}
3530 		zend_string_release_ex(cname, 0);
3531 
3532 		ftable = &fcc->calling_scope->function_table;
3533 		if (ce_org && !instanceof_function(ce_org, fcc->calling_scope)) {
3534 			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));
3535 			return 0;
3536 		}
3537 		mname = zend_string_init(Z_STRVAL_P(callable) + clen + 2, mlen, 0);
3538 	} else if (ce_org) {
3539 		/* Try to fetch find static method of given class. */
3540 		mname = Z_STR_P(callable);
3541 		zend_string_addref(mname);
3542 		ftable = &ce_org->function_table;
3543 		fcc->calling_scope = ce_org;
3544 	} else {
3545 		/* We already checked for plain function before. */
3546 		if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) {
3547 			zend_spprintf(error, 0, "function \"%s\" not found or invalid function name", Z_STRVAL_P(callable));
3548 		}
3549 		return 0;
3550 	}
3551 
3552 	lmname = zend_string_tolower(mname);
3553 	if (strict_class &&
3554 	    fcc->calling_scope &&
3555 		zend_string_equals_literal(lmname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
3556 		fcc->function_handler = fcc->calling_scope->constructor;
3557 		if (fcc->function_handler) {
3558 			retval = 1;
3559 		}
3560 	} else if ((zv = zend_hash_find(ftable, lmname)) != NULL) {
3561 		fcc->function_handler = Z_PTR_P(zv);
3562 		retval = 1;
3563 		if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) &&
3564 		    !strict_class) {
3565 			scope = get_scope(frame);
3566 			if (scope &&
3567 			    instanceof_function(fcc->function_handler->common.scope, scope)) {
3568 
3569 				zv = zend_hash_find(&scope->function_table, lmname);
3570 				if (zv != NULL) {
3571 					zend_function *priv_fbc = Z_PTR_P(zv);
3572 
3573 					if ((priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE)
3574 					 && priv_fbc->common.scope == scope) {
3575 						fcc->function_handler = priv_fbc;
3576 					}
3577 				}
3578 			}
3579 		}
3580 		if (!(fcc->function_handler->common.fn_flags & ZEND_ACC_PUBLIC) &&
3581 		    (fcc->calling_scope &&
3582 		     ((fcc->object && fcc->calling_scope->__call) ||
3583 		      (!fcc->object && fcc->calling_scope->__callstatic)))) {
3584 			scope = get_scope(frame);
3585 			if (fcc->function_handler->common.scope != scope) {
3586 				if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PRIVATE)
3587 				 || !zend_check_protected(zend_get_function_root_class(fcc->function_handler), scope)) {
3588 					retval = 0;
3589 					fcc->function_handler = NULL;
3590 					goto get_function_via_handler;
3591 				}
3592 			}
3593 		}
3594 	} else {
3595 get_function_via_handler:
3596 		if (fcc->object && fcc->calling_scope == ce_org) {
3597 			if (strict_class && ce_org->__call) {
3598 				fcc->function_handler = zend_get_call_trampoline_func(ce_org, mname, 0);
3599 				call_via_handler = 1;
3600 				retval = 1;
3601 			} else {
3602 				fcc->function_handler = fcc->object->handlers->get_method(&fcc->object, mname, NULL);
3603 				if (fcc->function_handler) {
3604 					if (strict_class &&
3605 					    (!fcc->function_handler->common.scope ||
3606 					     !instanceof_function(ce_org, fcc->function_handler->common.scope))) {
3607 						zend_release_fcall_info_cache(fcc);
3608 					} else {
3609 						retval = 1;
3610 						call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
3611 					}
3612 				}
3613 			}
3614 		} else if (fcc->calling_scope) {
3615 			if (fcc->calling_scope->get_static_method) {
3616 				fcc->function_handler = fcc->calling_scope->get_static_method(fcc->calling_scope, mname);
3617 			} else {
3618 				fcc->function_handler = zend_std_get_static_method(fcc->calling_scope, mname, NULL);
3619 			}
3620 			if (fcc->function_handler) {
3621 				retval = 1;
3622 				call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
3623 				if (call_via_handler && !fcc->object) {
3624 					zend_object *object = zend_get_this_object(frame);
3625 					if (object &&
3626 					    instanceof_function(object->ce, fcc->calling_scope)) {
3627 						fcc->object = object;
3628 					}
3629 				}
3630 			}
3631 		}
3632 	}
3633 
3634 	if (retval) {
3635 		if (fcc->calling_scope && !call_via_handler) {
3636 			if (fcc->function_handler->common.fn_flags & ZEND_ACC_ABSTRACT) {
3637 				retval = 0;
3638 				if (error) {
3639 					zend_spprintf(error, 0, "cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
3640 				}
3641 			} else if (!fcc->object && !(fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) {
3642 				retval = 0;
3643 				if (error) {
3644 					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));
3645 				}
3646 			}
3647 			if (retval
3648 			 && !(fcc->function_handler->common.fn_flags & ZEND_ACC_PUBLIC)) {
3649 				scope = get_scope(frame);
3650 				if (fcc->function_handler->common.scope != scope) {
3651 					if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PRIVATE)
3652 					 || (!zend_check_protected(zend_get_function_root_class(fcc->function_handler), scope))) {
3653 						if (error) {
3654 							if (*error) {
3655 								efree(*error);
3656 							}
3657 							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));
3658 						}
3659 						retval = 0;
3660 					}
3661 				}
3662 			}
3663 		}
3664 	} else if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) {
3665 		if (fcc->calling_scope) {
3666 			if (error) zend_spprintf(error, 0, "class %s does not have a method \"%s\"", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(mname));
3667 		} else {
3668 			if (error) zend_spprintf(error, 0, "function %s() does not exist", ZSTR_VAL(mname));
3669 		}
3670 	}
3671 	zend_string_release_ex(lmname, 0);
3672 	zend_string_release_ex(mname, 0);
3673 
3674 	if (fcc->object) {
3675 		fcc->called_scope = fcc->object->ce;
3676 		if (fcc->function_handler
3677 		 && (fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) {
3678 			fcc->object = NULL;
3679 		}
3680 	}
3681 	return retval;
3682 }
3683 /* }}} */
3684 
zend_get_callable_name_ex(zval * callable,zend_object * object)3685 ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *object) /* {{{ */
3686 {
3687 try_again:
3688 	switch (Z_TYPE_P(callable)) {
3689 		case IS_STRING:
3690 			if (object) {
3691 				return zend_create_member_string(object->ce->name, Z_STR_P(callable));
3692 			}
3693 			return zend_string_copy(Z_STR_P(callable));
3694 
3695 		case IS_ARRAY:
3696 		{
3697 			zval *method = NULL;
3698 			zval *obj = NULL;
3699 
3700 			if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
3701 				obj = zend_hash_index_find_deref(Z_ARRVAL_P(callable), 0);
3702 				method = zend_hash_index_find_deref(Z_ARRVAL_P(callable), 1);
3703 			}
3704 
3705 			if (obj == NULL || method == NULL || Z_TYPE_P(method) != IS_STRING) {
3706 				return ZSTR_KNOWN(ZEND_STR_ARRAY_CAPITALIZED);
3707 			}
3708 
3709 			if (Z_TYPE_P(obj) == IS_STRING) {
3710 				return zend_create_member_string(Z_STR_P(obj), Z_STR_P(method));
3711 			} else if (Z_TYPE_P(obj) == IS_OBJECT) {
3712 				return zend_create_member_string(Z_OBJCE_P(obj)->name, Z_STR_P(method));
3713 			} else {
3714 				return ZSTR_KNOWN(ZEND_STR_ARRAY_CAPITALIZED);
3715 			}
3716 		}
3717 		case IS_OBJECT:
3718 		{
3719 			zend_class_entry *ce = Z_OBJCE_P(callable);
3720 			return zend_string_concat2(
3721 				ZSTR_VAL(ce->name), ZSTR_LEN(ce->name),
3722 				"::__invoke", sizeof("::__invoke") - 1);
3723 		}
3724 		case IS_REFERENCE:
3725 			callable = Z_REFVAL_P(callable);
3726 			goto try_again;
3727 		default:
3728 			return zval_get_string_func(callable);
3729 	}
3730 }
3731 /* }}} */
3732 
zend_get_callable_name(zval * callable)3733 ZEND_API zend_string *zend_get_callable_name(zval *callable) /* {{{ */
3734 {
3735 	return zend_get_callable_name_ex(callable, NULL);
3736 }
3737 /* }}} */
3738 
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)3739 ZEND_API bool zend_is_callable_at_frame(
3740 		zval *callable, zend_object *object, zend_execute_data *frame,
3741 		uint32_t check_flags, zend_fcall_info_cache *fcc, char **error) /* {{{ */
3742 {
3743 	bool ret;
3744 	zend_fcall_info_cache fcc_local;
3745 	bool strict_class = 0;
3746 
3747 	if (fcc == NULL) {
3748 		fcc = &fcc_local;
3749 	}
3750 	if (error) {
3751 		*error = NULL;
3752 	}
3753 
3754 	fcc->calling_scope = NULL;
3755 	fcc->called_scope = NULL;
3756 	fcc->function_handler = NULL;
3757 	fcc->object = NULL;
3758 
3759 again:
3760 	switch (Z_TYPE_P(callable)) {
3761 		case IS_STRING:
3762 			if (object) {
3763 				fcc->object = object;
3764 				fcc->calling_scope = object->ce;
3765 			}
3766 
3767 			if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3768 				fcc->called_scope = fcc->calling_scope;
3769 				return 1;
3770 			}
3771 
3772 check_func:
3773 			ret = zend_is_callable_check_func(check_flags, callable, frame, fcc, strict_class, error);
3774 			if (fcc == &fcc_local) {
3775 				zend_release_fcall_info_cache(fcc);
3776 			}
3777 			return ret;
3778 
3779 		case IS_ARRAY:
3780 			{
3781 				zval *method = NULL;
3782 				zval *obj = NULL;
3783 
3784 				if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
3785 					obj = zend_hash_index_find(Z_ARRVAL_P(callable), 0);
3786 					method = zend_hash_index_find(Z_ARRVAL_P(callable), 1);
3787 				}
3788 
3789 				do {
3790 					if (obj == NULL || method == NULL) {
3791 						break;
3792 					}
3793 
3794 					ZVAL_DEREF(method);
3795 					if (Z_TYPE_P(method) != IS_STRING) {
3796 						break;
3797 					}
3798 
3799 					ZVAL_DEREF(obj);
3800 					if (Z_TYPE_P(obj) == IS_STRING) {
3801 						if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3802 							return 1;
3803 						}
3804 
3805 						if (!zend_is_callable_check_class(Z_STR_P(obj), get_scope(frame), frame, fcc, &strict_class, error)) {
3806 							return 0;
3807 						}
3808 
3809 					} else if (Z_TYPE_P(obj) == IS_OBJECT) {
3810 
3811 						fcc->calling_scope = Z_OBJCE_P(obj); /* TBFixed: what if it's overloaded? */
3812 
3813 						fcc->object = Z_OBJ_P(obj);
3814 
3815 						if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3816 							fcc->called_scope = fcc->calling_scope;
3817 							return 1;
3818 						}
3819 					} else {
3820 						break;
3821 					}
3822 
3823 					callable = method;
3824 					goto check_func;
3825 
3826 				} while (0);
3827 				if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
3828 					if (!obj || (!Z_ISREF_P(obj)?
3829 								(Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_OBJECT) :
3830 								(Z_TYPE_P(Z_REFVAL_P(obj)) != IS_STRING && Z_TYPE_P(Z_REFVAL_P(obj)) != IS_OBJECT))) {
3831 						if (error) *error = estrdup("first array member is not a valid class name or object");
3832 					} else {
3833 						if (error) *error = estrdup("second array member is not a valid method");
3834 					}
3835 				} else {
3836 					if (error) *error = estrdup("array must have exactly two members");
3837 				}
3838 			}
3839 			return 0;
3840 		case IS_OBJECT:
3841 			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) {
3842 				fcc->called_scope = fcc->calling_scope;
3843 				if (fcc == &fcc_local) {
3844 					zend_release_fcall_info_cache(fcc);
3845 				}
3846 				return 1;
3847 			}
3848 			if (error) *error = estrdup("no array or string given");
3849 			return 0;
3850 		case IS_REFERENCE:
3851 			callable = Z_REFVAL_P(callable);
3852 			goto again;
3853 		default:
3854 			if (error) *error = estrdup("no array or string given");
3855 			return 0;
3856 	}
3857 }
3858 /* }}} */
3859 
zend_is_callable_ex(zval * callable,zend_object * object,uint32_t check_flags,zend_string ** callable_name,zend_fcall_info_cache * fcc,char ** error)3860 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) /* {{{ */
3861 {
3862 	/* Determine callability at the first parent user frame. */
3863 	zend_execute_data *frame = EG(current_execute_data);
3864 	while (frame && (!frame->func || !ZEND_USER_CODE(frame->func->type))) {
3865 		frame = frame->prev_execute_data;
3866 	}
3867 
3868 	bool ret = zend_is_callable_at_frame(callable, object, frame, check_flags, fcc, error);
3869 	if (callable_name) {
3870 		*callable_name = zend_get_callable_name_ex(callable, object);
3871 	}
3872 	return ret;
3873 }
3874 
zend_is_callable(zval * callable,uint32_t check_flags,zend_string ** callable_name)3875 ZEND_API bool zend_is_callable(zval *callable, uint32_t check_flags, zend_string **callable_name) /* {{{ */
3876 {
3877 	return zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, NULL);
3878 }
3879 /* }}} */
3880 
zend_make_callable(zval * callable,zend_string ** callable_name)3881 ZEND_API bool zend_make_callable(zval *callable, zend_string **callable_name) /* {{{ */
3882 {
3883 	zend_fcall_info_cache fcc;
3884 
3885 	if (zend_is_callable_ex(callable, NULL, 0, callable_name, &fcc, NULL)) {
3886 		if (Z_TYPE_P(callable) == IS_STRING && fcc.calling_scope) {
3887 			zval_ptr_dtor_str(callable);
3888 			array_init(callable);
3889 			add_next_index_str(callable, zend_string_copy(fcc.calling_scope->name));
3890 			add_next_index_str(callable, zend_string_copy(fcc.function_handler->common.function_name));
3891 		}
3892 		zend_release_fcall_info_cache(&fcc);
3893 		return 1;
3894 	}
3895 	return 0;
3896 }
3897 /* }}} */
3898 
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)3899 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) /* {{{ */
3900 {
3901 	if (!zend_is_callable_ex(callable, NULL, check_flags, callable_name, fcc, error)) {
3902 		return FAILURE;
3903 	}
3904 
3905 	fci->size = sizeof(*fci);
3906 	fci->object = fcc->object;
3907 	ZVAL_COPY_VALUE(&fci->function_name, callable);
3908 	fci->retval = NULL;
3909 	fci->param_count = 0;
3910 	fci->params = NULL;
3911 	fci->named_params = NULL;
3912 
3913 	return SUCCESS;
3914 }
3915 /* }}} */
3916 
zend_fcall_info_args_clear(zend_fcall_info * fci,bool free_mem)3917 ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, bool free_mem) /* {{{ */
3918 {
3919 	if (fci->params) {
3920 		zval *p = fci->params;
3921 		zval *end = p + fci->param_count;
3922 
3923 		while (p != end) {
3924 			i_zval_ptr_dtor(p);
3925 			p++;
3926 		}
3927 		if (free_mem) {
3928 			efree(fci->params);
3929 			fci->params = NULL;
3930 		}
3931 	}
3932 	fci->param_count = 0;
3933 }
3934 /* }}} */
3935 
zend_fcall_info_args_save(zend_fcall_info * fci,uint32_t * param_count,zval ** params)3936 ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, uint32_t *param_count, zval **params) /* {{{ */
3937 {
3938 	*param_count = fci->param_count;
3939 	*params = fci->params;
3940 	fci->param_count = 0;
3941 	fci->params = NULL;
3942 }
3943 /* }}} */
3944 
zend_fcall_info_args_restore(zend_fcall_info * fci,uint32_t param_count,zval * params)3945 ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, uint32_t param_count, zval *params) /* {{{ */
3946 {
3947 	zend_fcall_info_args_clear(fci, 1);
3948 	fci->param_count = param_count;
3949 	fci->params = params;
3950 }
3951 /* }}} */
3952 
zend_fcall_info_args_ex(zend_fcall_info * fci,zend_function * func,zval * args)3953 ZEND_API zend_result zend_fcall_info_args_ex(zend_fcall_info *fci, zend_function *func, zval *args) /* {{{ */
3954 {
3955 	zval *arg, *params;
3956 	uint32_t n = 1;
3957 
3958 	zend_fcall_info_args_clear(fci, !args);
3959 
3960 	if (!args) {
3961 		return SUCCESS;
3962 	}
3963 
3964 	if (Z_TYPE_P(args) != IS_ARRAY) {
3965 		return FAILURE;
3966 	}
3967 
3968 	fci->param_count = zend_hash_num_elements(Z_ARRVAL_P(args));
3969 	fci->params = params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
3970 
3971 	ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args), arg) {
3972 		if (func && !Z_ISREF_P(arg) && ARG_SHOULD_BE_SENT_BY_REF(func, n)) {
3973 			ZVAL_NEW_REF(params, arg);
3974 			Z_TRY_ADDREF_P(arg);
3975 		} else {
3976 			ZVAL_COPY(params, arg);
3977 		}
3978 		params++;
3979 		n++;
3980 	} ZEND_HASH_FOREACH_END();
3981 
3982 	return SUCCESS;
3983 }
3984 /* }}} */
3985 
zend_fcall_info_args(zend_fcall_info * fci,zval * args)3986 ZEND_API zend_result zend_fcall_info_args(zend_fcall_info *fci, zval *args) /* {{{ */
3987 {
3988 	return zend_fcall_info_args_ex(fci, NULL, args);
3989 }
3990 /* }}} */
3991 
zend_fcall_info_argp(zend_fcall_info * fci,uint32_t argc,zval * argv)3992 ZEND_API void zend_fcall_info_argp(zend_fcall_info *fci, uint32_t argc, zval *argv) /* {{{ */
3993 {
3994 	zend_fcall_info_args_clear(fci, !argc);
3995 
3996 	if (argc) {
3997 		fci->param_count = argc;
3998 		fci->params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
3999 
4000 		for (uint32_t i = 0; i < argc; ++i) {
4001 			ZVAL_COPY(&fci->params[i], &argv[i]);
4002 		}
4003 	}
4004 }
4005 /* }}} */
4006 
zend_fcall_info_argv(zend_fcall_info * fci,uint32_t argc,va_list * argv)4007 ZEND_API void zend_fcall_info_argv(zend_fcall_info *fci, uint32_t argc, va_list *argv) /* {{{ */
4008 {
4009 	zend_fcall_info_args_clear(fci, !argc);
4010 
4011 	if (argc) {
4012 		zval *arg;
4013 		fci->param_count = argc;
4014 		fci->params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
4015 
4016 		for (uint32_t i = 0; i < argc; ++i) {
4017 			arg = va_arg(*argv, zval *);
4018 			ZVAL_COPY(&fci->params[i], arg);
4019 		}
4020 	}
4021 }
4022 /* }}} */
4023 
zend_fcall_info_argn(zend_fcall_info * fci,uint32_t argc,...)4024 ZEND_API void zend_fcall_info_argn(zend_fcall_info *fci, uint32_t argc, ...) /* {{{ */
4025 {
4026 	va_list argv;
4027 
4028 	va_start(argv, argc);
4029 	zend_fcall_info_argv(fci, argc, &argv);
4030 	va_end(argv);
4031 }
4032 /* }}} */
4033 
zend_fcall_info_call(zend_fcall_info * fci,zend_fcall_info_cache * fcc,zval * retval_ptr,zval * args)4034 ZEND_API zend_result zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval *retval_ptr, zval *args) /* {{{ */
4035 {
4036 	zval retval, *org_params = NULL;
4037 	uint32_t org_count = 0;
4038 	zend_result result;
4039 
4040 	fci->retval = retval_ptr ? retval_ptr : &retval;
4041 	if (args) {
4042 		zend_fcall_info_args_save(fci, &org_count, &org_params);
4043 		zend_fcall_info_args(fci, args);
4044 	}
4045 	result = zend_call_function(fci, fcc);
4046 
4047 	if (!retval_ptr && Z_TYPE(retval) != IS_UNDEF) {
4048 		zval_ptr_dtor(&retval);
4049 	}
4050 	if (args) {
4051 		zend_fcall_info_args_restore(fci, org_count, org_params);
4052 	}
4053 	return result;
4054 }
4055 /* }}} */
4056 
zend_get_module_version(const char * module_name)4057 ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */
4058 {
4059 	zend_string *lname;
4060 	size_t name_len = strlen(module_name);
4061 	zend_module_entry *module;
4062 
4063 	lname = zend_string_alloc(name_len, 0);
4064 	zend_str_tolower_copy(ZSTR_VAL(lname), module_name, name_len);
4065 	module = zend_hash_find_ptr(&module_registry, lname);
4066 	zend_string_efree(lname);
4067 	return module ? module->version : NULL;
4068 }
4069 /* }}} */
4070 
is_persistent_class(zend_class_entry * ce)4071 static zend_always_inline bool is_persistent_class(zend_class_entry *ce) {
4072 	return (ce->type & ZEND_INTERNAL_CLASS)
4073 		&& ce->info.internal.module->type == MODULE_PERSISTENT;
4074 }
4075 
zend_declare_typed_property(zend_class_entry * ce,zend_string * name,zval * property,int access_type,zend_string * doc_comment,zend_type type)4076 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) /* {{{ */
4077 {
4078 	zend_property_info *property_info, *property_info_ptr;
4079 
4080 	if (ZEND_TYPE_IS_SET(type)) {
4081 		ce->ce_flags |= ZEND_ACC_HAS_TYPE_HINTS;
4082 	}
4083 
4084 	if (ce->type == ZEND_INTERNAL_CLASS) {
4085 		property_info = pemalloc(sizeof(zend_property_info), 1);
4086 	} else {
4087 		property_info = zend_arena_alloc(&CG(arena), sizeof(zend_property_info));
4088 		if (Z_TYPE_P(property) == IS_CONSTANT_AST) {
4089 			ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
4090 			if (access_type & ZEND_ACC_STATIC) {
4091 				ce->ce_flags |= ZEND_ACC_HAS_AST_STATICS;
4092 			} else {
4093 				ce->ce_flags |= ZEND_ACC_HAS_AST_PROPERTIES;
4094 			}
4095 		}
4096 	}
4097 
4098 	if (Z_TYPE_P(property) == IS_STRING && !ZSTR_IS_INTERNED(Z_STR_P(property))) {
4099 		zval_make_interned_string(property);
4100 	}
4101 
4102 	if (!(access_type & ZEND_ACC_PPP_MASK)) {
4103 		access_type |= ZEND_ACC_PUBLIC;
4104 	}
4105 	if (access_type & ZEND_ACC_STATIC) {
4106 		if ((property_info_ptr = zend_hash_find_ptr(&ce->properties_info, name)) != NULL &&
4107 		    (property_info_ptr->flags & ZEND_ACC_STATIC) != 0) {
4108 			property_info->offset = property_info_ptr->offset;
4109 			zval_ptr_dtor(&ce->default_static_members_table[property_info->offset]);
4110 			zend_hash_del(&ce->properties_info, name);
4111 		} else {
4112 			property_info->offset = ce->default_static_members_count++;
4113 			ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
4114 		}
4115 		ZVAL_COPY_VALUE(&ce->default_static_members_table[property_info->offset], property);
4116 		if (!ZEND_MAP_PTR(ce->static_members_table)) {
4117 			if (ce->type == ZEND_INTERNAL_CLASS &&
4118 					ce->info.internal.module->type == MODULE_PERSISTENT) {
4119 				ZEND_MAP_PTR_NEW(ce->static_members_table);
4120 			} else {
4121 				ZEND_MAP_PTR_INIT(ce->static_members_table,
4122 					zend_arena_alloc(&CG(arena), sizeof(zval **)));
4123 				ZEND_MAP_PTR_SET(ce->static_members_table, NULL);
4124 			}
4125 		}
4126 	} else {
4127 		zval *property_default_ptr;
4128 		if ((property_info_ptr = zend_hash_find_ptr(&ce->properties_info, name)) != NULL &&
4129 		    (property_info_ptr->flags & ZEND_ACC_STATIC) == 0) {
4130 			property_info->offset = property_info_ptr->offset;
4131 			zval_ptr_dtor(&ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)]);
4132 			zend_hash_del(&ce->properties_info, name);
4133 
4134 			ZEND_ASSERT(ce->type == ZEND_INTERNAL_CLASS);
4135 			ZEND_ASSERT(ce->properties_info_table != NULL);
4136 			ce->properties_info_table[OBJ_PROP_TO_NUM(property_info->offset)] = property_info;
4137 		} else {
4138 			property_info->offset = OBJ_PROP_TO_OFFSET(ce->default_properties_count);
4139 			ce->default_properties_count++;
4140 			ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
4141 
4142 			/* For user classes this is handled during linking */
4143 			if (ce->type == ZEND_INTERNAL_CLASS) {
4144 				ce->properties_info_table = perealloc(ce->properties_info_table, sizeof(zend_property_info *) * ce->default_properties_count, 1);
4145 				ce->properties_info_table[ce->default_properties_count - 1] = property_info;
4146 			}
4147 		}
4148 		property_default_ptr = &ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)];
4149 		ZVAL_COPY_VALUE(property_default_ptr, property);
4150 		Z_PROP_FLAG_P(property_default_ptr) = Z_ISUNDEF_P(property) ? IS_PROP_UNINIT : 0;
4151 	}
4152 	if (ce->type & ZEND_INTERNAL_CLASS) {
4153 		/* Must be interned to avoid ZTS data races */
4154 		if (is_persistent_class(ce)) {
4155 			name = zend_new_interned_string(zend_string_copy(name));
4156 		}
4157 
4158 		if (Z_REFCOUNTED_P(property)) {
4159 			zend_error_noreturn(E_CORE_ERROR, "Internal zvals cannot be refcounted");
4160 		}
4161 	}
4162 
4163 	if (access_type & ZEND_ACC_PUBLIC) {
4164 		property_info->name = zend_string_copy(name);
4165 	} else if (access_type & ZEND_ACC_PRIVATE) {
4166 		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));
4167 	} else {
4168 		ZEND_ASSERT(access_type & ZEND_ACC_PROTECTED);
4169 		property_info->name = zend_mangle_property_name("*", 1, ZSTR_VAL(name), ZSTR_LEN(name), is_persistent_class(ce));
4170 	}
4171 
4172 	property_info->name = zend_new_interned_string(property_info->name);
4173 	property_info->flags = access_type;
4174 	property_info->doc_comment = doc_comment;
4175 	property_info->attributes = NULL;
4176 	property_info->ce = ce;
4177 	property_info->type = type;
4178 
4179 	if (is_persistent_class(ce)) {
4180 		zend_type *single_type;
4181 		ZEND_TYPE_FOREACH(property_info->type, single_type) {
4182 			if (ZEND_TYPE_HAS_NAME(*single_type)) {
4183 				zend_string *name = zend_new_interned_string(ZEND_TYPE_NAME(*single_type));
4184 				ZEND_TYPE_SET_PTR(*single_type, name);
4185 				zend_alloc_ce_cache(name);
4186 			}
4187 		} ZEND_TYPE_FOREACH_END();
4188 	}
4189 
4190 	zend_hash_update_ptr(&ce->properties_info, name, property_info);
4191 
4192 	return property_info;
4193 }
4194 /* }}} */
4195 
zend_try_assign_typed_ref_ex(zend_reference * ref,zval * val,bool strict)4196 ZEND_API zend_result zend_try_assign_typed_ref_ex(zend_reference *ref, zval *val, bool strict) /* {{{ */
4197 {
4198 	if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, val, strict))) {
4199 		zval_ptr_dtor(val);
4200 		return FAILURE;
4201 	} else {
4202 		zval_ptr_dtor(&ref->val);
4203 		ZVAL_COPY_VALUE(&ref->val, val);
4204 		return SUCCESS;
4205 	}
4206 }
4207 /* }}} */
4208 
zend_try_assign_typed_ref(zend_reference * ref,zval * val)4209 ZEND_API zend_result zend_try_assign_typed_ref(zend_reference *ref, zval *val) /* {{{ */
4210 {
4211 	return zend_try_assign_typed_ref_ex(ref, val, ZEND_ARG_USES_STRICT_TYPES());
4212 }
4213 /* }}} */
4214 
zend_try_assign_typed_ref_null(zend_reference * ref)4215 ZEND_API zend_result zend_try_assign_typed_ref_null(zend_reference *ref) /* {{{ */
4216 {
4217 	zval tmp;
4218 
4219 	ZVAL_NULL(&tmp);
4220 	return zend_try_assign_typed_ref(ref, &tmp);
4221 }
4222 /* }}} */
4223 
zend_try_assign_typed_ref_bool(zend_reference * ref,bool val)4224 ZEND_API zend_result zend_try_assign_typed_ref_bool(zend_reference *ref, bool val) /* {{{ */
4225 {
4226 	zval tmp;
4227 
4228 	ZVAL_BOOL(&tmp, val);
4229 	return zend_try_assign_typed_ref(ref, &tmp);
4230 }
4231 /* }}} */
4232 
zend_try_assign_typed_ref_long(zend_reference * ref,zend_long lval)4233 ZEND_API zend_result zend_try_assign_typed_ref_long(zend_reference *ref, zend_long lval) /* {{{ */
4234 {
4235 	zval tmp;
4236 
4237 	ZVAL_LONG(&tmp, lval);
4238 	return zend_try_assign_typed_ref(ref, &tmp);
4239 }
4240 /* }}} */
4241 
zend_try_assign_typed_ref_double(zend_reference * ref,double dval)4242 ZEND_API zend_result zend_try_assign_typed_ref_double(zend_reference *ref, double dval) /* {{{ */
4243 {
4244 	zval tmp;
4245 
4246 	ZVAL_DOUBLE(&tmp, dval);
4247 	return zend_try_assign_typed_ref(ref, &tmp);
4248 }
4249 /* }}} */
4250 
zend_try_assign_typed_ref_empty_string(zend_reference * ref)4251 ZEND_API zend_result zend_try_assign_typed_ref_empty_string(zend_reference *ref) /* {{{ */
4252 {
4253 	zval tmp;
4254 
4255 	ZVAL_EMPTY_STRING(&tmp);
4256 	return zend_try_assign_typed_ref(ref, &tmp);
4257 }
4258 /* }}} */
4259 
zend_try_assign_typed_ref_str(zend_reference * ref,zend_string * str)4260 ZEND_API zend_result zend_try_assign_typed_ref_str(zend_reference *ref, zend_string *str) /* {{{ */
4261 {
4262 	zval tmp;
4263 
4264 	ZVAL_STR(&tmp, str);
4265 	return zend_try_assign_typed_ref(ref, &tmp);
4266 }
4267 /* }}} */
4268 
zend_try_assign_typed_ref_string(zend_reference * ref,const char * string)4269 ZEND_API zend_result zend_try_assign_typed_ref_string(zend_reference *ref, const char *string) /* {{{ */
4270 {
4271 	zval tmp;
4272 
4273 	ZVAL_STRING(&tmp, string);
4274 	return zend_try_assign_typed_ref(ref, &tmp);
4275 }
4276 /* }}} */
4277 
zend_try_assign_typed_ref_stringl(zend_reference * ref,const char * string,size_t len)4278 ZEND_API zend_result zend_try_assign_typed_ref_stringl(zend_reference *ref, const char *string, size_t len) /* {{{ */
4279 {
4280 	zval tmp;
4281 
4282 	ZVAL_STRINGL(&tmp, string, len);
4283 	return zend_try_assign_typed_ref(ref, &tmp);
4284 }
4285 /* }}} */
4286 
zend_try_assign_typed_ref_arr(zend_reference * ref,zend_array * arr)4287 ZEND_API zend_result zend_try_assign_typed_ref_arr(zend_reference *ref, zend_array *arr) /* {{{ */
4288 {
4289 	zval tmp;
4290 
4291 	ZVAL_ARR(&tmp, arr);
4292 	return zend_try_assign_typed_ref(ref, &tmp);
4293 }
4294 /* }}} */
4295 
zend_try_assign_typed_ref_res(zend_reference * ref,zend_resource * res)4296 ZEND_API zend_result zend_try_assign_typed_ref_res(zend_reference *ref, zend_resource *res) /* {{{ */
4297 {
4298 	zval tmp;
4299 
4300 	ZVAL_RES(&tmp, res);
4301 	return zend_try_assign_typed_ref(ref, &tmp);
4302 }
4303 /* }}} */
4304 
zend_try_assign_typed_ref_zval(zend_reference * ref,zval * zv)4305 ZEND_API zend_result zend_try_assign_typed_ref_zval(zend_reference *ref, zval *zv) /* {{{ */
4306 {
4307 	zval tmp;
4308 
4309 	ZVAL_COPY_VALUE(&tmp, zv);
4310 	return zend_try_assign_typed_ref(ref, &tmp);
4311 }
4312 /* }}} */
4313 
zend_try_assign_typed_ref_zval_ex(zend_reference * ref,zval * zv,bool strict)4314 ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval *zv, bool strict) /* {{{ */
4315 {
4316 	zval tmp;
4317 
4318 	ZVAL_COPY_VALUE(&tmp, zv);
4319 	return zend_try_assign_typed_ref_ex(ref, &tmp, strict);
4320 }
4321 /* }}} */
4322 
zend_declare_property_ex(zend_class_entry * ce,zend_string * name,zval * property,int access_type,zend_string * doc_comment)4323 ZEND_API void zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment) /* {{{ */
4324 {
4325 	zend_declare_typed_property(ce, name, property, access_type, doc_comment, (zend_type) ZEND_TYPE_INIT_NONE(0));
4326 }
4327 /* }}} */
4328 
zend_declare_property(zend_class_entry * ce,const char * name,size_t name_length,zval * property,int access_type)4329 ZEND_API void zend_declare_property(zend_class_entry *ce, const char *name, size_t name_length, zval *property, int access_type) /* {{{ */
4330 {
4331 	zend_string *key = zend_string_init(name, name_length, is_persistent_class(ce));
4332 	zend_declare_property_ex(ce, key, property, access_type, NULL);
4333 	zend_string_release(key);
4334 }
4335 /* }}} */
4336 
zend_declare_property_null(zend_class_entry * ce,const char * name,size_t name_length,int access_type)4337 ZEND_API void zend_declare_property_null(zend_class_entry *ce, const char *name, size_t name_length, int access_type) /* {{{ */
4338 {
4339 	zval property;
4340 
4341 	ZVAL_NULL(&property);
4342 	zend_declare_property(ce, name, name_length, &property, access_type);
4343 }
4344 /* }}} */
4345 
zend_declare_property_bool(zend_class_entry * ce,const char * name,size_t name_length,zend_long value,int access_type)4346 ZEND_API void zend_declare_property_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type) /* {{{ */
4347 {
4348 	zval property;
4349 
4350 	ZVAL_BOOL(&property, value);
4351 	zend_declare_property(ce, name, name_length, &property, access_type);
4352 }
4353 /* }}} */
4354 
zend_declare_property_long(zend_class_entry * ce,const char * name,size_t name_length,zend_long value,int access_type)4355 ZEND_API void zend_declare_property_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type) /* {{{ */
4356 {
4357 	zval property;
4358 
4359 	ZVAL_LONG(&property, value);
4360 	zend_declare_property(ce, name, name_length, &property, access_type);
4361 }
4362 /* }}} */
4363 
zend_declare_property_double(zend_class_entry * ce,const char * name,size_t name_length,double value,int access_type)4364 ZEND_API void zend_declare_property_double(zend_class_entry *ce, const char *name, size_t name_length, double value, int access_type) /* {{{ */
4365 {
4366 	zval property;
4367 
4368 	ZVAL_DOUBLE(&property, value);
4369 	zend_declare_property(ce, name, name_length, &property, access_type);
4370 }
4371 /* }}} */
4372 
zend_declare_property_string(zend_class_entry * ce,const char * name,size_t name_length,const char * value,int access_type)4373 ZEND_API void zend_declare_property_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value, int access_type) /* {{{ */
4374 {
4375 	zval property;
4376 
4377 	ZVAL_NEW_STR(&property, zend_string_init(value, strlen(value), ce->type & ZEND_INTERNAL_CLASS));
4378 	zend_declare_property(ce, name, name_length, &property, access_type);
4379 }
4380 /* }}} */
4381 
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)4382 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) /* {{{ */
4383 {
4384 	zval property;
4385 
4386 	ZVAL_NEW_STR(&property, zend_string_init(value, value_len, ce->type & ZEND_INTERNAL_CLASS));
4387 	zend_declare_property(ce, name, name_length, &property, access_type);
4388 }
4389 /* }}} */
4390 
zend_declare_class_constant_ex(zend_class_entry * ce,zend_string * name,zval * value,int flags,zend_string * doc_comment)4391 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) /* {{{ */
4392 {
4393 	zend_class_constant *c;
4394 
4395 	if (ce->ce_flags & ZEND_ACC_INTERFACE) {
4396 		if (!(flags & ZEND_ACC_PUBLIC)) {
4397 			zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface constant %s::%s must be public", ZSTR_VAL(ce->name), ZSTR_VAL(name));
4398 		}
4399 	}
4400 
4401 	if (zend_string_equals_literal_ci(name, "class")) {
4402 		zend_error_noreturn(ce->type == ZEND_INTERNAL_CLASS ? E_CORE_ERROR : E_COMPILE_ERROR,
4403 				"A class constant must not be called 'class'; it is reserved for class name fetching");
4404 	}
4405 
4406 	if (Z_TYPE_P(value) == IS_STRING && !ZSTR_IS_INTERNED(Z_STR_P(value))) {
4407 		zval_make_interned_string(value);
4408 	}
4409 
4410 	if (ce->type == ZEND_INTERNAL_CLASS) {
4411 		c = pemalloc(sizeof(zend_class_constant), 1);
4412 	} else {
4413 		c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
4414 	}
4415 	ZVAL_COPY_VALUE(&c->value, value);
4416 	ZEND_CLASS_CONST_FLAGS(c) = flags;
4417 	c->doc_comment = doc_comment;
4418 	c->attributes = NULL;
4419 	c->ce = ce;
4420 	if (Z_TYPE_P(value) == IS_CONSTANT_AST) {
4421 		ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
4422 		ce->ce_flags |= ZEND_ACC_HAS_AST_CONSTANTS;
4423 		if (ce->type == ZEND_INTERNAL_CLASS && !ZEND_MAP_PTR(ce->mutable_data)) {
4424 			ZEND_MAP_PTR_NEW(ce->mutable_data);
4425 		}
4426 	}
4427 
4428 	if (!zend_hash_add_ptr(&ce->constants_table, name, c)) {
4429 		zend_error_noreturn(ce->type == ZEND_INTERNAL_CLASS ? E_CORE_ERROR : E_COMPILE_ERROR,
4430 			"Cannot redefine class constant %s::%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
4431 	}
4432 
4433 	return c;
4434 }
4435 /* }}} */
4436 
zend_declare_class_constant(zend_class_entry * ce,const char * name,size_t name_length,zval * value)4437 ZEND_API void zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value) /* {{{ */
4438 {
4439 	zend_string *key;
4440 
4441 	if (ce->type == ZEND_INTERNAL_CLASS) {
4442 		key = zend_string_init_interned(name, name_length, 1);
4443 	} else {
4444 		key = zend_string_init(name, name_length, 0);
4445 	}
4446 	zend_declare_class_constant_ex(ce, key, value, ZEND_ACC_PUBLIC, NULL);
4447 	zend_string_release(key);
4448 }
4449 /* }}} */
4450 
zend_declare_class_constant_null(zend_class_entry * ce,const char * name,size_t name_length)4451 ZEND_API void zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length) /* {{{ */
4452 {
4453 	zval constant;
4454 
4455 	ZVAL_NULL(&constant);
4456 	zend_declare_class_constant(ce, name, name_length, &constant);
4457 }
4458 /* }}} */
4459 
zend_declare_class_constant_long(zend_class_entry * ce,const char * name,size_t name_length,zend_long value)4460 ZEND_API void zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value) /* {{{ */
4461 {
4462 	zval constant;
4463 
4464 	ZVAL_LONG(&constant, value);
4465 	zend_declare_class_constant(ce, name, name_length, &constant);
4466 }
4467 /* }}} */
4468 
zend_declare_class_constant_bool(zend_class_entry * ce,const char * name,size_t name_length,bool value)4469 ZEND_API void zend_declare_class_constant_bool(zend_class_entry *ce, const char *name, size_t name_length, bool value) /* {{{ */
4470 {
4471 	zval constant;
4472 
4473 	ZVAL_BOOL(&constant, value);
4474 	zend_declare_class_constant(ce, name, name_length, &constant);
4475 }
4476 /* }}} */
4477 
zend_declare_class_constant_double(zend_class_entry * ce,const char * name,size_t name_length,double value)4478 ZEND_API void zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value) /* {{{ */
4479 {
4480 	zval constant;
4481 
4482 	ZVAL_DOUBLE(&constant, value);
4483 	zend_declare_class_constant(ce, name, name_length, &constant);
4484 }
4485 /* }}} */
4486 
zend_declare_class_constant_stringl(zend_class_entry * ce,const char * name,size_t name_length,const char * value,size_t value_length)4487 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) /* {{{ */
4488 {
4489 	zval constant;
4490 
4491 	ZVAL_NEW_STR(&constant, zend_string_init(value, value_length, ce->type & ZEND_INTERNAL_CLASS));
4492 	zend_declare_class_constant(ce, name, name_length, &constant);
4493 }
4494 /* }}} */
4495 
zend_declare_class_constant_string(zend_class_entry * ce,const char * name,size_t name_length,const char * value)4496 ZEND_API void zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value) /* {{{ */
4497 {
4498 	zend_declare_class_constant_stringl(ce, name, name_length, value, strlen(value));
4499 }
4500 /* }}} */
4501 
zend_update_property_ex(zend_class_entry * scope,zend_object * object,zend_string * name,zval * value)4502 ZEND_API void zend_update_property_ex(zend_class_entry *scope, zend_object *object, zend_string *name, zval *value) /* {{{ */
4503 {
4504 	zend_class_entry *old_scope = EG(fake_scope);
4505 
4506 	EG(fake_scope) = scope;
4507 
4508 	object->handlers->write_property(object, name, value, NULL);
4509 
4510 	EG(fake_scope) = old_scope;
4511 }
4512 /* }}} */
4513 
zend_update_property(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,zval * value)4514 ZEND_API void zend_update_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zval *value) /* {{{ */
4515 {
4516 	zend_string *property;
4517 	zend_class_entry *old_scope = EG(fake_scope);
4518 
4519 	EG(fake_scope) = scope;
4520 
4521 	property = zend_string_init(name, name_length, 0);
4522 	object->handlers->write_property(object, property, value, NULL);
4523 	zend_string_release_ex(property, 0);
4524 
4525 	EG(fake_scope) = old_scope;
4526 }
4527 /* }}} */
4528 
zend_update_property_null(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length)4529 ZEND_API void zend_update_property_null(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length) /* {{{ */
4530 {
4531 	zval tmp;
4532 
4533 	ZVAL_NULL(&tmp);
4534 	zend_update_property(scope, object, name, name_length, &tmp);
4535 }
4536 /* }}} */
4537 
zend_unset_property(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length)4538 ZEND_API void zend_unset_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length) /* {{{ */
4539 {
4540 	zend_string *property;
4541 	zend_class_entry *old_scope = EG(fake_scope);
4542 
4543 	EG(fake_scope) = scope;
4544 
4545 	property = zend_string_init(name, name_length, 0);
4546 	object->handlers->unset_property(object, property, 0);
4547 	zend_string_release_ex(property, 0);
4548 
4549 	EG(fake_scope) = old_scope;
4550 }
4551 /* }}} */
4552 
zend_update_property_bool(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,zend_long value)4553 ZEND_API void zend_update_property_bool(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_long value) /* {{{ */
4554 {
4555 	zval tmp;
4556 
4557 	ZVAL_BOOL(&tmp, value);
4558 	zend_update_property(scope, object, name, name_length, &tmp);
4559 }
4560 /* }}} */
4561 
zend_update_property_long(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,zend_long value)4562 ZEND_API void zend_update_property_long(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_long value) /* {{{ */
4563 {
4564 	zval tmp;
4565 
4566 	ZVAL_LONG(&tmp, value);
4567 	zend_update_property(scope, object, name, name_length, &tmp);
4568 }
4569 /* }}} */
4570 
zend_update_property_double(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,double value)4571 ZEND_API void zend_update_property_double(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, double value) /* {{{ */
4572 {
4573 	zval tmp;
4574 
4575 	ZVAL_DOUBLE(&tmp, value);
4576 	zend_update_property(scope, object, name, name_length, &tmp);
4577 }
4578 /* }}} */
4579 
zend_update_property_str(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,zend_string * value)4580 ZEND_API void zend_update_property_str(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_string *value) /* {{{ */
4581 {
4582 	zval tmp;
4583 
4584 	ZVAL_STR(&tmp, value);
4585 	zend_update_property(scope, object, name, name_length, &tmp);
4586 }
4587 /* }}} */
4588 
zend_update_property_string(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,const char * value)4589 ZEND_API void zend_update_property_string(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, const char *value) /* {{{ */
4590 {
4591 	zval tmp;
4592 
4593 	ZVAL_STRING(&tmp, value);
4594 	Z_SET_REFCOUNT(tmp, 0);
4595 	zend_update_property(scope, object, name, name_length, &tmp);
4596 }
4597 /* }}} */
4598 
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)4599 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) /* {{{ */
4600 {
4601 	zval tmp;
4602 
4603 	ZVAL_STRINGL(&tmp, value, value_len);
4604 	Z_SET_REFCOUNT(tmp, 0);
4605 	zend_update_property(scope, object, name, name_length, &tmp);
4606 }
4607 /* }}} */
4608 
zend_update_static_property_ex(zend_class_entry * scope,zend_string * name,zval * value)4609 ZEND_API zend_result zend_update_static_property_ex(zend_class_entry *scope, zend_string *name, zval *value) /* {{{ */
4610 {
4611 	zval *property, tmp;
4612 	zend_property_info *prop_info;
4613 	zend_class_entry *old_scope = EG(fake_scope);
4614 
4615 	if (UNEXPECTED(!(scope->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
4616 		if (UNEXPECTED(zend_update_class_constants(scope)) != SUCCESS) {
4617 			return FAILURE;
4618 		}
4619 	}
4620 
4621 	EG(fake_scope) = scope;
4622 	property = zend_std_get_static_property_with_info(scope, name, BP_VAR_W, &prop_info);
4623 	EG(fake_scope) = old_scope;
4624 
4625 	if (!property) {
4626 		return FAILURE;
4627 	}
4628 
4629 	ZEND_ASSERT(!Z_ISREF_P(value));
4630 	Z_TRY_ADDREF_P(value);
4631 	if (ZEND_TYPE_IS_SET(prop_info->type)) {
4632 		ZVAL_COPY_VALUE(&tmp, value);
4633 		if (!zend_verify_property_type(prop_info, &tmp, /* strict */ 0)) {
4634 			Z_TRY_DELREF_P(value);
4635 			return FAILURE;
4636 		}
4637 		value = &tmp;
4638 	}
4639 
4640 	zend_assign_to_variable(property, value, IS_TMP_VAR, /* strict */ 0);
4641 	return SUCCESS;
4642 }
4643 /* }}} */
4644 
zend_update_static_property(zend_class_entry * scope,const char * name,size_t name_length,zval * value)4645 ZEND_API zend_result zend_update_static_property(zend_class_entry *scope, const char *name, size_t name_length, zval *value) /* {{{ */
4646 {
4647 	zend_string *key = zend_string_init(name, name_length, 0);
4648 	bool retval = zend_update_static_property_ex(scope, key, value);
4649 	zend_string_efree(key);
4650 	return retval;
4651 }
4652 /* }}} */
4653 
zend_update_static_property_null(zend_class_entry * scope,const char * name,size_t name_length)4654 ZEND_API zend_result zend_update_static_property_null(zend_class_entry *scope, const char *name, size_t name_length) /* {{{ */
4655 {
4656 	zval tmp;
4657 
4658 	ZVAL_NULL(&tmp);
4659 	return zend_update_static_property(scope, name, name_length, &tmp);
4660 }
4661 /* }}} */
4662 
zend_update_static_property_bool(zend_class_entry * scope,const char * name,size_t name_length,zend_long value)4663 ZEND_API zend_result zend_update_static_property_bool(zend_class_entry *scope, const char *name, size_t name_length, zend_long value) /* {{{ */
4664 {
4665 	zval tmp;
4666 
4667 	ZVAL_BOOL(&tmp, value);
4668 	return zend_update_static_property(scope, name, name_length, &tmp);
4669 }
4670 /* }}} */
4671 
zend_update_static_property_long(zend_class_entry * scope,const char * name,size_t name_length,zend_long value)4672 ZEND_API zend_result zend_update_static_property_long(zend_class_entry *scope, const char *name, size_t name_length, zend_long value) /* {{{ */
4673 {
4674 	zval tmp;
4675 
4676 	ZVAL_LONG(&tmp, value);
4677 	return zend_update_static_property(scope, name, name_length, &tmp);
4678 }
4679 /* }}} */
4680 
zend_update_static_property_double(zend_class_entry * scope,const char * name,size_t name_length,double value)4681 ZEND_API zend_result zend_update_static_property_double(zend_class_entry *scope, const char *name, size_t name_length, double value) /* {{{ */
4682 {
4683 	zval tmp;
4684 
4685 	ZVAL_DOUBLE(&tmp, value);
4686 	return zend_update_static_property(scope, name, name_length, &tmp);
4687 }
4688 /* }}} */
4689 
zend_update_static_property_string(zend_class_entry * scope,const char * name,size_t name_length,const char * value)4690 ZEND_API zend_result zend_update_static_property_string(zend_class_entry *scope, const char *name, size_t name_length, const char *value) /* {{{ */
4691 {
4692 	zval tmp;
4693 
4694 	ZVAL_STRING(&tmp, value);
4695 	Z_SET_REFCOUNT(tmp, 0);
4696 	return zend_update_static_property(scope, name, name_length, &tmp);
4697 }
4698 /* }}} */
4699 
zend_update_static_property_stringl(zend_class_entry * scope,const char * name,size_t name_length,const char * value,size_t value_len)4700 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) /* {{{ */
4701 {
4702 	zval tmp;
4703 
4704 	ZVAL_STRINGL(&tmp, value, value_len);
4705 	Z_SET_REFCOUNT(tmp, 0);
4706 	return zend_update_static_property(scope, name, name_length, &tmp);
4707 }
4708 /* }}} */
4709 
zend_read_property_ex(zend_class_entry * scope,zend_object * object,zend_string * name,bool silent,zval * rv)4710 ZEND_API zval *zend_read_property_ex(zend_class_entry *scope, zend_object *object, zend_string *name, bool silent, zval *rv) /* {{{ */
4711 {
4712 	zval *value;
4713 	zend_class_entry *old_scope = EG(fake_scope);
4714 
4715 	EG(fake_scope) = scope;
4716 
4717 	value = object->handlers->read_property(object, name, silent?BP_VAR_IS:BP_VAR_R, NULL, rv);
4718 
4719 	EG(fake_scope) = old_scope;
4720 	return value;
4721 }
4722 /* }}} */
4723 
zend_read_property(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,bool silent,zval * rv)4724 ZEND_API zval *zend_read_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, bool silent, zval *rv) /* {{{ */
4725 {
4726 	zval *value;
4727 	zend_string *str;
4728 
4729 	str = zend_string_init(name, name_length, 0);
4730 	value = zend_read_property_ex(scope, object, str, silent, rv);
4731 	zend_string_release_ex(str, 0);
4732 	return value;
4733 }
4734 /* }}} */
4735 
zend_read_static_property_ex(zend_class_entry * scope,zend_string * name,bool silent)4736 ZEND_API zval *zend_read_static_property_ex(zend_class_entry *scope, zend_string *name, bool silent) /* {{{ */
4737 {
4738 	zval *property;
4739 	zend_class_entry *old_scope = EG(fake_scope);
4740 
4741 	EG(fake_scope) = scope;
4742 	property = zend_std_get_static_property(scope, name, silent ? BP_VAR_IS : BP_VAR_R);
4743 	EG(fake_scope) = old_scope;
4744 
4745 	return property;
4746 }
4747 /* }}} */
4748 
zend_read_static_property(zend_class_entry * scope,const char * name,size_t name_length,bool silent)4749 ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, size_t name_length, bool silent) /* {{{ */
4750 {
4751 	zend_string *key = zend_string_init(name, name_length, 0);
4752 	zval *property = zend_read_static_property_ex(scope, key, silent);
4753 	zend_string_efree(key);
4754 	return property;
4755 }
4756 /* }}} */
4757 
zend_save_error_handling(zend_error_handling * current)4758 ZEND_API void zend_save_error_handling(zend_error_handling *current) /* {{{ */
4759 {
4760 	current->handling = EG(error_handling);
4761 	current->exception = EG(exception_class);
4762 }
4763 /* }}} */
4764 
zend_replace_error_handling(zend_error_handling_t error_handling,zend_class_entry * exception_class,zend_error_handling * current)4765 ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current) /* {{{ */
4766 {
4767 	if (current) {
4768 		zend_save_error_handling(current);
4769 	}
4770 	ZEND_ASSERT(error_handling == EH_THROW || exception_class == NULL);
4771 	EG(error_handling) = error_handling;
4772 	EG(exception_class) = exception_class;
4773 }
4774 /* }}} */
4775 
zend_restore_error_handling(zend_error_handling * saved)4776 ZEND_API void zend_restore_error_handling(zend_error_handling *saved) /* {{{ */
4777 {
4778 	EG(error_handling) = saved->handling;
4779 	EG(exception_class) = saved->exception;
4780 }
4781 /* }}} */
4782 
zend_get_object_type(const zend_class_entry * ce)4783 ZEND_API ZEND_COLD const char *zend_get_object_type(const zend_class_entry *ce) /* {{{ */
4784 {
4785 	if(ce->ce_flags & ZEND_ACC_TRAIT) {
4786 		return "trait";
4787 	} else if (ce->ce_flags & ZEND_ACC_INTERFACE) {
4788 		return "interface";
4789 	} else {
4790 		return "class";
4791 	}
4792 }
4793 /* }}} */
4794 
zend_is_iterable(zval * iterable)4795 ZEND_API bool zend_is_iterable(zval *iterable) /* {{{ */
4796 {
4797 	switch (Z_TYPE_P(iterable)) {
4798 		case IS_ARRAY:
4799 			return 1;
4800 		case IS_OBJECT:
4801 			return zend_class_implements_interface(Z_OBJCE_P(iterable), zend_ce_traversable);
4802 		default:
4803 			return 0;
4804 	}
4805 }
4806 /* }}} */
4807 
zend_is_countable(zval * countable)4808 ZEND_API bool zend_is_countable(zval *countable) /* {{{ */
4809 {
4810 	switch (Z_TYPE_P(countable)) {
4811 		case IS_ARRAY:
4812 			return 1;
4813 		case IS_OBJECT:
4814 			if (Z_OBJ_HT_P(countable)->count_elements) {
4815 				return 1;
4816 			}
4817 
4818 			return zend_class_implements_interface(Z_OBJCE_P(countable), zend_ce_countable);
4819 		default:
4820 			return 0;
4821 	}
4822 }
4823 /* }}} */
4824 
get_default_via_ast(zval * default_value_zval,const char * default_value)4825 static zend_result get_default_via_ast(zval *default_value_zval, const char *default_value) {
4826 	zend_ast *ast;
4827 	zend_arena *ast_arena;
4828 
4829 	zend_string *code = zend_string_concat3(
4830 		"<?php ", sizeof("<?php ") - 1, default_value, strlen(default_value), ";", 1);
4831 
4832 	ast = zend_compile_string_to_ast(code, &ast_arena, ZSTR_EMPTY_ALLOC());
4833 	zend_string_release(code);
4834 
4835 	if (!ast) {
4836 		return FAILURE;
4837 	}
4838 
4839 	zend_ast_list *statement_list = zend_ast_get_list(ast);
4840 	zend_ast **const_expr_ast_ptr = &statement_list->child[0];
4841 
4842 	zend_arena *original_ast_arena = CG(ast_arena);
4843 	uint32_t original_compiler_options = CG(compiler_options);
4844 	zend_file_context original_file_context;
4845 	CG(ast_arena) = ast_arena;
4846 	/* Disable constant substitution, to make getDefaultValueConstant() work. */
4847 	CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION | ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION;
4848 	zend_file_context_begin(&original_file_context);
4849 	zend_const_expr_to_zval(default_value_zval, const_expr_ast_ptr, /* allow_dynamic */ true);
4850 	CG(ast_arena) = original_ast_arena;
4851 	CG(compiler_options) = original_compiler_options;
4852 	zend_file_context_end(&original_file_context);
4853 
4854 	zend_ast_destroy(ast);
4855 	zend_arena_destroy(ast_arena);
4856 
4857 	return SUCCESS;
4858 }
4859 
try_parse_string(const char * str,size_t len,char quote)4860 static zend_string *try_parse_string(const char *str, size_t len, char quote) {
4861 	if (len == 0) {
4862 		return ZSTR_EMPTY_ALLOC();
4863 	}
4864 
4865 	for (size_t i = 0; i < len; i++) {
4866 		if (str[i] == '\\' || str[i] == quote) {
4867 			return NULL;
4868 		}
4869 	}
4870 	return zend_string_init(str, len, 0);
4871 }
4872 
zend_get_default_from_internal_arg_info(zval * default_value_zval,zend_internal_arg_info * arg_info)4873 ZEND_API zend_result zend_get_default_from_internal_arg_info(
4874 		zval *default_value_zval, zend_internal_arg_info *arg_info)
4875 {
4876 	const char *default_value = arg_info->default_value;
4877 	if (!default_value) {
4878 		return FAILURE;
4879 	}
4880 
4881 	/* Avoid going through the full AST machinery for some simple and common cases. */
4882 	size_t default_value_len = strlen(default_value);
4883 	zend_ulong lval;
4884 	if (default_value_len == sizeof("null")-1
4885 			&& !memcmp(default_value, "null", sizeof("null")-1)) {
4886 		ZVAL_NULL(default_value_zval);
4887 		return SUCCESS;
4888 	} else if (default_value_len == sizeof("true")-1
4889 			&& !memcmp(default_value, "true", sizeof("true")-1)) {
4890 		ZVAL_TRUE(default_value_zval);
4891 		return SUCCESS;
4892 	} else if (default_value_len == sizeof("false")-1
4893 			&& !memcmp(default_value, "false", sizeof("false")-1)) {
4894 		ZVAL_FALSE(default_value_zval);
4895 		return SUCCESS;
4896 	} else if (default_value_len >= 2
4897 			&& (default_value[0] == '\'' || default_value[0] == '"')
4898 			&& default_value[default_value_len - 1] == default_value[0]) {
4899 		zend_string *str = try_parse_string(
4900 			default_value + 1, default_value_len - 2, default_value[0]);
4901 		if (str) {
4902 			ZVAL_STR(default_value_zval, str);
4903 			return SUCCESS;
4904 		}
4905 	} else if (default_value_len == sizeof("[]")-1
4906 			&& !memcmp(default_value, "[]", sizeof("[]")-1)) {
4907 		ZVAL_EMPTY_ARRAY(default_value_zval);
4908 		return SUCCESS;
4909 	} else if (ZEND_HANDLE_NUMERIC_STR(default_value, default_value_len, lval)) {
4910 		ZVAL_LONG(default_value_zval, lval);
4911 		return SUCCESS;
4912 	}
4913 
4914 #if 0
4915 	fprintf(stderr, "Evaluating %s via AST\n", default_value);
4916 #endif
4917 	return get_default_via_ast(default_value_zval, default_value);
4918 }
4919