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