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