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