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