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