1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) Zend Technologies Ltd. (http://www.zend.com)           |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 2.00 of the Zend license,     |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.zend.com/license/2_00.txt.                                |
11    | If you did not receive a copy of the Zend license and are unable to  |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@zend.com so we can mail you a copy immediately.              |
14    +----------------------------------------------------------------------+
15    | Authors: Andi Gutmans <andi@php.net>                                 |
16    |          Zeev Suraski <zeev@php.net>                                 |
17    |          Andrei Zmievski <andrei@php.net>                            |
18    |          Dmitry Stogov <dmitry@php.net>                              |
19    +----------------------------------------------------------------------+
20 */
21 
22 #include "zend.h"
23 #include "zend_execute.h"
24 #include "zend_API.h"
25 #include "zend_modules.h"
26 #include "zend_extensions.h"
27 #include "zend_constants.h"
28 #include "zend_interfaces.h"
29 #include "zend_exceptions.h"
30 #include "zend_closures.h"
31 #include "zend_inheritance.h"
32 #include "zend_ini.h"
33 
34 #include <stdarg.h>
35 
36 /* these variables are true statics/globals, and have to be mutex'ed on every access */
37 ZEND_API HashTable module_registry;
38 
39 static zend_module_entry **module_request_startup_handlers;
40 static zend_module_entry **module_request_shutdown_handlers;
41 static zend_module_entry **module_post_deactivate_handlers;
42 
43 static zend_class_entry  **class_cleanup_handlers;
44 
_zend_get_parameters_array_ex(int param_count, zval *argument_array)45 ZEND_API int _zend_get_parameters_array_ex(int param_count, zval *argument_array) /* {{{ */
46 {
47 	zval *param_ptr;
48 	int arg_count;
49 
50 	param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1);
51 	arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
52 
53 	if (param_count>arg_count) {
54 		return FAILURE;
55 	}
56 
57 	while (param_count-->0) {
58 		ZVAL_COPY_VALUE(argument_array, param_ptr);
59 		argument_array++;
60 		param_ptr++;
61 	}
62 
63 	return SUCCESS;
64 }
65 /* }}} */
66 
zend_copy_parameters_array(int param_count, zval *argument_array)67 ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array) /* {{{ */
68 {
69 	zval *param_ptr;
70 	int arg_count;
71 
72 	param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1);
73 	arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
74 
75 	if (param_count>arg_count) {
76 		return FAILURE;
77 	}
78 
79 	while (param_count-->0) {
80 		Z_TRY_ADDREF_P(param_ptr);
81 		zend_hash_next_index_insert_new(Z_ARRVAL_P(argument_array), param_ptr);
82 		param_ptr++;
83 	}
84 
85 	return SUCCESS;
86 }
87 /* }}} */
88 
zend_wrong_param_count(void)89 ZEND_API ZEND_COLD void zend_wrong_param_count(void) /* {{{ */
90 {
91 	const char *space;
92 	const char *class_name = get_active_class_name(&space);
93 
94 	zend_internal_argument_count_error(ZEND_ARG_USES_STRICT_TYPES(), "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name());
95 }
96 /* }}} */
97 
98 /* Argument parsing API -- andrei */
zend_get_type_by_const(int type)99 ZEND_API char *zend_get_type_by_const(int type) /* {{{ */
100 {
101 	switch(type) {
102 		case IS_FALSE:
103 		case IS_TRUE:
104 		case _IS_BOOL:
105 			return "bool";
106 		case IS_LONG:
107 			return "int";
108 		case IS_DOUBLE:
109 			return "float";
110 		case IS_STRING:
111 			return "string";
112 		case IS_OBJECT:
113 			return "object";
114 		case IS_RESOURCE:
115 			return "resource";
116 		case IS_NULL:
117 			return "null";
118 		case IS_CALLABLE:
119 			return "callable";
120 		case IS_ITERABLE:
121 			return "iterable";
122 		case IS_ARRAY:
123 			return "array";
124 		case IS_VOID:
125 			return "void";
126 		case _IS_NUMBER:
127 			return "number";
128 		default:
129 			return "unknown";
130 	}
131 }
132 /* }}} */
133 
zend_zval_type_name(const zval *arg)134 ZEND_API char *zend_zval_type_name(const zval *arg) /* {{{ */
135 {
136 	ZVAL_DEREF(arg);
137 	return zend_get_type_by_const(Z_TYPE_P(arg));
138 }
139 /* }}} */
140 
zend_zval_get_type(const zval *arg)141 ZEND_API zend_string *zend_zval_get_type(const zval *arg) /* {{{ */
142 {
143 	switch (Z_TYPE_P(arg)) {
144 		case IS_NULL:
145 			return ZSTR_KNOWN(ZEND_STR_NULL);
146 		case IS_FALSE:
147 		case IS_TRUE:
148 			return ZSTR_KNOWN(ZEND_STR_BOOLEAN);
149 		case IS_LONG:
150 			return ZSTR_KNOWN(ZEND_STR_INTEGER);
151 		case IS_DOUBLE:
152 			return ZSTR_KNOWN(ZEND_STR_DOUBLE);
153 		case IS_STRING:
154 			return ZSTR_KNOWN(ZEND_STR_STRING);
155 		case IS_ARRAY:
156 			return ZSTR_KNOWN(ZEND_STR_ARRAY);
157 		case IS_OBJECT:
158 			return ZSTR_KNOWN(ZEND_STR_OBJECT);
159 		case IS_RESOURCE:
160 			if (zend_rsrc_list_get_rsrc_type(Z_RES_P(arg))) {
161 				return ZSTR_KNOWN(ZEND_STR_RESOURCE);
162 			} else {
163 				return ZSTR_KNOWN(ZEND_STR_CLOSED_RESOURCE);
164 			}
165 		default:
166 			return NULL;
167 	}
168 }
169 /* }}} */
170 
zend_wrong_parameters_none_error(void)171 ZEND_API ZEND_COLD int ZEND_FASTCALL zend_wrong_parameters_none_error(void) /* {{{ */
172 {
173 	int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
174 	zend_function *active_function = EG(current_execute_data)->func;
175 	const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
176 
177 	zend_internal_argument_count_error(
178 				ZEND_ARG_USES_STRICT_TYPES(),
179 				"%s%s%s() expects %s %d parameter%s, %d given",
180 				class_name, \
181 				class_name[0] ? "::" : "", \
182 				ZSTR_VAL(active_function->common.function_name),
183 				"exactly",
184 				0,
185 				"s",
186 				num_args);
187 	return FAILURE;
188 }
189 /* }}} */
190 
zend_wrong_parameters_none_exception(void)191 ZEND_API ZEND_COLD int ZEND_FASTCALL zend_wrong_parameters_none_exception(void) /* {{{ */
192 {
193 	int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
194 	zend_function *active_function = EG(current_execute_data)->func;
195 	const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
196 
197 	zend_internal_argument_count_error(
198 				1,
199 				"%s%s%s() expects %s %d parameter%s, %d given",
200 				class_name, \
201 				class_name[0] ? "::" : "", \
202 				ZSTR_VAL(active_function->common.function_name),
203 				"exactly",
204 				0,
205 				"s",
206 				num_args);
207 	return FAILURE;
208 }
209 /* }}} */
210 
zend_wrong_parameters_count_error(int min_num_args, int max_num_args)211 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_error(int min_num_args, int max_num_args) /* {{{ */
212 {
213 	int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
214 	zend_function *active_function = EG(current_execute_data)->func;
215 	const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
216 
217 	zend_internal_argument_count_error(
218 				ZEND_ARG_USES_STRICT_TYPES(),
219 				"%s%s%s() expects %s %d parameter%s, %d given",
220 				class_name, \
221 				class_name[0] ? "::" : "", \
222 				ZSTR_VAL(active_function->common.function_name),
223 				min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
224 				num_args < min_num_args ? min_num_args : max_num_args,
225 				(num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
226 				num_args);
227 }
228 /* }}} */
229 
zend_wrong_parameters_count_exception(int min_num_args, int max_num_args)230 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_exception(int min_num_args, int max_num_args) /* {{{ */
231 {
232 	int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
233 	zend_function *active_function = EG(current_execute_data)->func;
234 	const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
235 
236 	zend_internal_argument_count_error(
237 				1,
238 				"%s%s%s() expects %s %d parameter%s, %d given",
239 				class_name, \
240 				class_name[0] ? "::" : "", \
241 				ZSTR_VAL(active_function->common.function_name),
242 				min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
243 				num_args < min_num_args ? min_num_args : max_num_args,
244 				(num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
245 				num_args);
246 }
247 /* }}} */
248 
zend_wrong_parameter_type_error(int num, zend_expected_type expected_type, zval *arg)249 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(int num, zend_expected_type expected_type, zval *arg) /* {{{ */
250 {
251 	const char *space;
252 	const char *class_name;
253 	static const char * const expected_error[] = {
254 		Z_EXPECTED_TYPES(Z_EXPECTED_TYPE_STR)
255 		NULL
256 	};
257 
258 	if (EG(exception)) {
259 		return;
260 	}
261 	class_name = get_active_class_name(&space);
262 	zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be %s, %s given",
263 		class_name, space, get_active_function_name(), num, expected_error[expected_type], zend_zval_type_name(arg));
264 }
265 /* }}} */
266 
zend_wrong_parameter_type_exception(int num, zend_expected_type expected_type, zval *arg)267 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_exception(int num, zend_expected_type expected_type, zval *arg) /* {{{ */
268 {
269 	const char *space;
270 	const char *class_name;
271 	static const char * const expected_error[] = {
272 		Z_EXPECTED_TYPES(Z_EXPECTED_TYPE_STR)
273 		NULL
274 	};
275 
276 	if (EG(exception)) {
277 		return;
278 	}
279 	class_name = get_active_class_name(&space);
280 	zend_internal_type_error(1, "%s%s%s() expects parameter %d to be %s, %s given",
281 		class_name, space, get_active_function_name(), num, expected_error[expected_type], zend_zval_type_name(arg));
282 }
283 /* }}} */
284 
zend_wrong_parameter_class_error(int num, char *name, zval *arg)285 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(int num, char *name, zval *arg) /* {{{ */
286 {
287 	const char *space;
288 	const char *class_name;
289 
290 	if (EG(exception)) {
291 		return;
292 	}
293 	class_name = get_active_class_name(&space);
294 	zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be %s, %s given",
295 		class_name, space, get_active_function_name(), num, name, zend_zval_type_name(arg));
296 }
297 /* }}} */
298 
zend_wrong_parameter_class_exception(int num, char *name, zval *arg)299 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_exception(int num, char *name, zval *arg) /* {{{ */
300 {
301 	const char *space;
302 	const char *class_name;
303 
304 	if (EG(exception)) {
305 		return;
306 	}
307 	class_name = get_active_class_name(&space);
308 	zend_internal_type_error(1, "%s%s%s() expects parameter %d to be %s, %s given",
309 		class_name, space, get_active_function_name(), num, name, zend_zval_type_name(arg));
310 }
311 /* }}} */
312 
zend_wrong_callback_error(int num, char *error)313 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(int num, char *error) /* {{{ */
314 {
315 	const char *space;
316 	const char *class_name;
317 
318 	if (EG(exception)) {
319 		return;
320 	}
321 	class_name = get_active_class_name(&space);
322 	zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a valid callback, %s",
323 		class_name, space, get_active_function_name(), num, error);
324 	efree(error);
325 }
326 /* }}} */
327 
zend_wrong_callback_exception(int num, char *error)328 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_exception(int num, char *error) /* {{{ */
329 {
330 	const char *space;
331 	const char *class_name;
332 
333 	if (EG(exception)) {
334 		return;
335 	}
336 	class_name = get_active_class_name(&space);
337 	zend_internal_type_error(1, "%s%s%s() expects parameter %d to be a valid callback, %s",
338 		class_name, space, get_active_function_name(), num, error);
339 	efree(error);
340 }
341 /* }}} */
342 
zend_wrong_callback_deprecated(int num, char *error)343 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_deprecated(int num, char *error) /* {{{ */
344 {
345 	const char *space;
346 	const char *class_name = get_active_class_name(&space);
347 
348 	zend_error(E_DEPRECATED, "%s%s%s() expects parameter %d to be a valid callback, %s",
349 		class_name, space, get_active_function_name(), num, error);
350 	efree(error);
351 }
352 /* }}} */
353 
zend_parse_arg_class(zval *arg, zend_class_entry **pce, int num, int check_null)354 ZEND_API int ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **pce, int num, int check_null) /* {{{ */
355 {
356 	zend_class_entry *ce_base = *pce;
357 
358 	if (check_null && Z_TYPE_P(arg) == IS_NULL) {
359 		*pce = NULL;
360 		return 1;
361 	}
362 	if (!try_convert_to_string(arg)) {
363 		*pce = NULL;
364 		return 0;
365 	}
366 
367 	*pce = zend_lookup_class(Z_STR_P(arg));
368 	if (ce_base) {
369 		if ((!*pce || !instanceof_function(*pce, ce_base))) {
370 			const char *space;
371 			const char *class_name = get_active_class_name(&space);
372 
373 			zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a class name derived from %s, '%s' given",
374 				class_name, space, get_active_function_name(), num,
375 				ZSTR_VAL(ce_base->name), Z_STRVAL_P(arg));
376 			*pce = NULL;
377 			return 0;
378 		}
379 	}
380 	if (!*pce) {
381 		const char *space;
382 		const char *class_name = get_active_class_name(&space);
383 
384 		zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects parameter %d to be a valid class name, '%s' given",
385 			class_name, space, get_active_function_name(), num,
386 			Z_STRVAL_P(arg));
387 		return 0;
388 	}
389 	return 1;
390 }
391 /* }}} */
392 
zend_parse_arg_bool_weak(zval *arg, zend_bool *dest)393 ZEND_API int ZEND_FASTCALL zend_parse_arg_bool_weak(zval *arg, zend_bool *dest) /* {{{ */
394 {
395 	if (EXPECTED(Z_TYPE_P(arg) <= IS_STRING)) {
396 		*dest = zend_is_true(arg);
397 	} else {
398 		return 0;
399 	}
400 	return 1;
401 }
402 /* }}} */
403 
zend_parse_arg_bool_slow(zval *arg, zend_bool *dest)404 ZEND_API int ZEND_FASTCALL zend_parse_arg_bool_slow(zval *arg, zend_bool *dest) /* {{{ */
405 {
406 	if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
407 		return 0;
408 	}
409 	return zend_parse_arg_bool_weak(arg, dest);
410 }
411 /* }}} */
412 
zend_parse_arg_long_weak(zval *arg, zend_long *dest)413 ZEND_API int ZEND_FASTCALL zend_parse_arg_long_weak(zval *arg, zend_long *dest) /* {{{ */
414 {
415 	if (EXPECTED(Z_TYPE_P(arg) == IS_DOUBLE)) {
416 		if (UNEXPECTED(zend_isnan(Z_DVAL_P(arg)))) {
417 			return 0;
418 		}
419 		if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(Z_DVAL_P(arg)))) {
420 			return 0;
421 		} else {
422 			*dest = zend_dval_to_lval(Z_DVAL_P(arg));
423 		}
424 	} else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
425 		double d;
426 		int type;
427 
428 		if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), dest, &d)) != IS_LONG)) {
429 			if (EXPECTED(type != 0)) {
430 				if (UNEXPECTED(zend_isnan(d))) {
431 					return 0;
432 				}
433 				if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(d))) {
434 					return 0;
435 				} else {
436 					*dest = zend_dval_to_lval(d);
437 				}
438 			} else {
439 				return 0;
440 			}
441 		}
442 		if (UNEXPECTED(EG(exception))) {
443 			return 0;
444 		}
445 	} else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
446 		*dest = 0;
447 	} else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
448 		*dest = 1;
449 	} else {
450 		return 0;
451 	}
452 	return 1;
453 }
454 /* }}} */
455 
zend_parse_arg_long_slow(zval *arg, zend_long *dest)456 ZEND_API int ZEND_FASTCALL zend_parse_arg_long_slow(zval *arg, zend_long *dest) /* {{{ */
457 {
458 	if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
459 		return 0;
460 	}
461 	return zend_parse_arg_long_weak(arg, dest);
462 }
463 /* }}} */
464 
zend_parse_arg_long_cap_weak(zval *arg, zend_long *dest)465 ZEND_API int ZEND_FASTCALL zend_parse_arg_long_cap_weak(zval *arg, zend_long *dest) /* {{{ */
466 {
467 	if (EXPECTED(Z_TYPE_P(arg) == IS_DOUBLE)) {
468 		if (UNEXPECTED(zend_isnan(Z_DVAL_P(arg)))) {
469 			return 0;
470 		}
471 		*dest = zend_dval_to_lval_cap(Z_DVAL_P(arg));
472 	} else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
473 		double d;
474 		int type;
475 
476 		if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), dest, &d)) != IS_LONG)) {
477 			if (EXPECTED(type != 0)) {
478 				if (UNEXPECTED(zend_isnan(d))) {
479 					return 0;
480 				}
481 				*dest = zend_dval_to_lval_cap(d);
482 			} else {
483 				return 0;
484 			}
485 		}
486 		if (UNEXPECTED(EG(exception))) {
487 			return 0;
488 		}
489 	} else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
490 		*dest = 0;
491 	} else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
492 		*dest = 1;
493 	} else {
494 		return 0;
495 	}
496 	return 1;
497 }
498 /* }}} */
499 
zend_parse_arg_long_cap_slow(zval *arg, zend_long *dest)500 ZEND_API int ZEND_FASTCALL zend_parse_arg_long_cap_slow(zval *arg, zend_long *dest) /* {{{ */
501 {
502 	if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
503 		return 0;
504 	}
505 	return zend_parse_arg_long_cap_weak(arg, dest);
506 }
507 /* }}} */
508 
zend_parse_arg_double_weak(zval *arg, double *dest)509 ZEND_API int ZEND_FASTCALL zend_parse_arg_double_weak(zval *arg, double *dest) /* {{{ */
510 {
511 	if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
512 		*dest = (double)Z_LVAL_P(arg);
513 	} else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
514 		zend_long l;
515 		int type;
516 
517 		if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), &l, dest)) != IS_DOUBLE)) {
518 			if (EXPECTED(type != 0)) {
519 				*dest = (double)(l);
520 			} else {
521 				return 0;
522 			}
523 		}
524 		if (UNEXPECTED(EG(exception))) {
525 			return 0;
526 		}
527 	} else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
528 		*dest = 0.0;
529 	} else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
530 		*dest = 1.0;
531 	} else {
532 		return 0;
533 	}
534 	return 1;
535 }
536 /* }}} */
537 
zend_parse_arg_double_slow(zval *arg, double *dest)538 ZEND_API int ZEND_FASTCALL zend_parse_arg_double_slow(zval *arg, double *dest) /* {{{ */
539 {
540 	if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
541 		/* SSTH Exception: IS_LONG may be accepted instead as IS_DOUBLE */
542 		*dest = (double)Z_LVAL_P(arg);
543 	} else if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
544 		return 0;
545 	}
546 	return zend_parse_arg_double_weak(arg, dest);
547 }
548 /* }}} */
549 
zend_parse_arg_str_weak(zval *arg, zend_string **dest)550 ZEND_API int ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest) /* {{{ */
551 {
552 	if (EXPECTED(Z_TYPE_P(arg) < IS_STRING)) {
553 		convert_to_string(arg);
554 		*dest = Z_STR_P(arg);
555 	} else if (UNEXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
556 		if (Z_OBJ_HANDLER_P(arg, cast_object)) {
557 			zval obj;
558 			if (Z_OBJ_HANDLER_P(arg, cast_object)(arg, &obj, IS_STRING) == SUCCESS) {
559 				zval_ptr_dtor(arg);
560 				ZVAL_COPY_VALUE(arg, &obj);
561 				*dest = Z_STR_P(arg);
562 				return 1;
563 			}
564 		} else if (Z_OBJ_HANDLER_P(arg, get)) {
565 			zval rv;
566 			zval *z = Z_OBJ_HANDLER_P(arg, get)(arg, &rv);
567 
568 			if (Z_TYPE_P(z) != IS_OBJECT) {
569 				zval_ptr_dtor(arg);
570 				if (Z_TYPE_P(z) == IS_STRING) {
571 					ZVAL_COPY_VALUE(arg, z);
572 				} else {
573 					ZVAL_STR(arg, zval_get_string_func(z));
574 					zval_ptr_dtor(z);
575 				}
576 				*dest = Z_STR_P(arg);
577 				return 1;
578 			}
579 			zval_ptr_dtor(z);
580 		}
581 		return 0;
582 	} else {
583 		return 0;
584 	}
585 	return 1;
586 }
587 /* }}} */
588 
zend_parse_arg_str_slow(zval *arg, zend_string **dest)589 ZEND_API int ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, zend_string **dest) /* {{{ */
590 {
591 	if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
592 		return 0;
593 	}
594 	return zend_parse_arg_str_weak(arg, dest);
595 }
596 /* }}} */
597 
zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, const char **spec, char **error, int *severity)598 static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, const char **spec, char **error, int *severity) /* {{{ */
599 {
600 	const char *spec_walk = *spec;
601 	char c = *spec_walk++;
602 	int check_null = 0;
603 	int separate = 0;
604 	zval *real_arg = arg;
605 
606 	/* scan through modifiers */
607 	ZVAL_DEREF(arg);
608 	while (1) {
609 		if (*spec_walk == '/') {
610 			SEPARATE_ZVAL_NOREF(arg);
611 			real_arg = arg;
612 			separate = 1;
613 		} else if (*spec_walk == '!') {
614 			check_null = 1;
615 		} else {
616 			break;
617 		}
618 		spec_walk++;
619 	}
620 
621 	switch (c) {
622 		case 'l':
623 		case 'L':
624 			{
625 				zend_long *p = va_arg(*va, zend_long *);
626 				zend_bool *is_null = NULL;
627 
628 				if (check_null) {
629 					is_null = va_arg(*va, zend_bool *);
630 				}
631 
632 				if (!zend_parse_arg_long(arg, p, is_null, check_null, c == 'L')) {
633 					return "int";
634 				}
635 			}
636 			break;
637 
638 		case 'd':
639 			{
640 				double *p = va_arg(*va, double *);
641 				zend_bool *is_null = NULL;
642 
643 				if (check_null) {
644 					is_null = va_arg(*va, zend_bool *);
645 				}
646 
647 				if (!zend_parse_arg_double(arg, p, is_null, check_null)) {
648 					return "float";
649 				}
650 			}
651 			break;
652 
653 		case 's':
654 			{
655 				char **p = va_arg(*va, char **);
656 				size_t *pl = va_arg(*va, size_t *);
657 				if (!zend_parse_arg_string(arg, p, pl, check_null)) {
658 					return "string";
659 				}
660 			}
661 			break;
662 
663 		case 'p':
664 			{
665 				char **p = va_arg(*va, char **);
666 				size_t *pl = va_arg(*va, size_t *);
667 				if (!zend_parse_arg_path(arg, p, pl, check_null)) {
668 					return "a valid path";
669 				}
670 			}
671 			break;
672 
673 		case 'P':
674 			{
675 				zend_string **str = va_arg(*va, zend_string **);
676 				if (!zend_parse_arg_path_str(arg, str, check_null)) {
677 					return "a valid path";
678 				}
679 			}
680 			break;
681 
682 		case 'S':
683 			{
684 				zend_string **str = va_arg(*va, zend_string **);
685 				if (!zend_parse_arg_str(arg, str, check_null)) {
686 					return "string";
687 				}
688 			}
689 			break;
690 
691 		case 'b':
692 			{
693 				zend_bool *p = va_arg(*va, zend_bool *);
694 				zend_bool *is_null = NULL;
695 
696 				if (check_null) {
697 					is_null = va_arg(*va, zend_bool *);
698 				}
699 
700 				if (!zend_parse_arg_bool(arg, p, is_null, check_null)) {
701 					return "bool";
702 				}
703 			}
704 			break;
705 
706 		case 'r':
707 			{
708 				zval **p = va_arg(*va, zval **);
709 
710 				if (!zend_parse_arg_resource(arg, p, check_null)) {
711 					return "resource";
712 				}
713 			}
714 			break;
715 
716 		case 'A':
717 		case 'a':
718 			{
719 				zval **p = va_arg(*va, zval **);
720 
721 				if (!zend_parse_arg_array(arg, p, check_null, c == 'A')) {
722 					return "array";
723 				}
724 			}
725 			break;
726 
727 		case 'H':
728 		case 'h':
729 			{
730 				HashTable **p = va_arg(*va, HashTable **);
731 
732 				if (!zend_parse_arg_array_ht(arg, p, check_null, c == 'H', separate)) {
733 					return "array";
734 				}
735 			}
736 			break;
737 
738 		case 'o':
739 			{
740 				zval **p = va_arg(*va, zval **);
741 
742 				if (!zend_parse_arg_object(arg, p, NULL, check_null)) {
743 					return "object";
744 				}
745 			}
746 			break;
747 
748 		case 'O':
749 			{
750 				zval **p = va_arg(*va, zval **);
751 				zend_class_entry *ce = va_arg(*va, zend_class_entry *);
752 
753 				if (!zend_parse_arg_object(arg, p, ce, check_null)) {
754 					if (ce) {
755 						return ZSTR_VAL(ce->name);
756 					} else {
757 						return "object";
758 					}
759 				}
760 			}
761 			break;
762 
763 		case 'C':
764 			{
765 				zend_class_entry *lookup, **pce = va_arg(*va, zend_class_entry **);
766 				zend_class_entry *ce_base = *pce;
767 
768 				if (check_null && Z_TYPE_P(arg) == IS_NULL) {
769 					*pce = NULL;
770 					break;
771 				}
772 				if (!try_convert_to_string(arg)) {
773 					*pce = NULL;
774 					return "valid class name";
775 				}
776 
777 				if ((lookup = zend_lookup_class(Z_STR_P(arg))) == NULL) {
778 					*pce = NULL;
779 				} else {
780 					*pce = lookup;
781 				}
782 				if (ce_base) {
783 					if ((!*pce || !instanceof_function(*pce, ce_base))) {
784 						zend_spprintf(error, 0, "to be a class name derived from %s, '%s' given",
785 							ZSTR_VAL(ce_base->name), Z_STRVAL_P(arg));
786 						*pce = NULL;
787 						return "";
788 					}
789 				}
790 				if (!*pce) {
791 					zend_spprintf(error, 0, "to be a valid class name, '%s' given",
792 						Z_STRVAL_P(arg));
793 					return "";
794 				}
795 				break;
796 
797 			}
798 			break;
799 
800 		case 'f':
801 			{
802 				zend_fcall_info *fci = va_arg(*va, zend_fcall_info *);
803 				zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *);
804 				char *is_callable_error = NULL;
805 
806 				if (check_null && Z_TYPE_P(arg) == IS_NULL) {
807 					fci->size = 0;
808 					fcc->function_handler = 0;
809 					break;
810 				}
811 
812 				if (zend_fcall_info_init(arg, 0, fci, fcc, NULL, &is_callable_error) == SUCCESS) {
813 					if (is_callable_error) {
814 						*severity = E_DEPRECATED;
815 						zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error);
816 						efree(is_callable_error);
817 						*spec = spec_walk;
818 						return "";
819 					}
820 					break;
821 				} else {
822 					if (is_callable_error) {
823 						*severity = E_ERROR;
824 						zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error);
825 						efree(is_callable_error);
826 						return "";
827 					} else {
828 						return "valid callback";
829 					}
830 				}
831 			}
832 
833 		case 'z':
834 			{
835 				zval **p = va_arg(*va, zval **);
836 
837 				zend_parse_arg_zval_deref(real_arg, p, check_null);
838 			}
839 			break;
840 
841 		case 'Z':
842 			/* 'Z' iz not supported anymore and should be replaced with 'z' */
843 			ZEND_ASSERT(c != 'Z');
844 		default:
845 			return "unknown";
846 	}
847 
848 	*spec = spec_walk;
849 
850 	return NULL;
851 }
852 /* }}} */
853 
zend_parse_arg(int arg_num, zval *arg, va_list *va, const char **spec, int flags)854 static int zend_parse_arg(int arg_num, zval *arg, va_list *va, const char **spec, int flags) /* {{{ */
855 {
856 	const char *expected_type = NULL;
857 	char *error = NULL;
858 	int severity = 0;
859 
860 	expected_type = zend_parse_arg_impl(arg_num, arg, va, spec, &error, &severity);
861 	if (expected_type) {
862 		if (EG(exception)) {
863 			return FAILURE;
864 		}
865 		if (!(flags & ZEND_PARSE_PARAMS_QUIET) && (*expected_type || error)) {
866 			const char *space;
867 			const char *class_name = get_active_class_name(&space);
868 			zend_bool throw_exception =
869 				ZEND_ARG_USES_STRICT_TYPES() || (flags & ZEND_PARSE_PARAMS_THROW);
870 
871 			if (error) {
872 				zend_internal_type_error(throw_exception, "%s%s%s() expects parameter %d %s",
873 						class_name, space, get_active_function_name(), arg_num, error);
874 				efree(error);
875 			} else {
876 				zend_internal_type_error(throw_exception,
877 						"%s%s%s() expects parameter %d to be %s, %s given",
878 						class_name, space, get_active_function_name(), arg_num, expected_type,
879 						zend_zval_type_name(arg));
880 			}
881 		}
882 		if (severity != E_DEPRECATED) {
883 			return FAILURE;
884 		}
885 	}
886 
887 	return SUCCESS;
888 }
889 /* }}} */
890 
zend_parse_parameter(int flags, int arg_num, zval *arg, const char *spec, ...)891 ZEND_API int zend_parse_parameter(int flags, int arg_num, zval *arg, const char *spec, ...)
892 {
893 	va_list va;
894 	int ret;
895 
896 	va_start(va, spec);
897 	ret = zend_parse_arg(arg_num, arg, &va, &spec, flags);
898 	va_end(va);
899 
900 	return ret;
901 }
902 
zend_parse_parameters_debug_error(const char *msg)903 static ZEND_COLD void zend_parse_parameters_debug_error(const char *msg) {
904 	zend_function *active_function = EG(current_execute_data)->func;
905 	const char *class_name = active_function->common.scope
906 		? ZSTR_VAL(active_function->common.scope->name) : "";
907 	zend_error_noreturn(E_CORE_ERROR, "%s%s%s(): %s",
908 		class_name, class_name[0] ? "::" : "",
909 		ZSTR_VAL(active_function->common.function_name), msg);
910 }
911 
zend_parse_va_args(int num_args, const char *type_spec, va_list *va, int flags)912 static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, int flags) /* {{{ */
913 {
914 	const  char *spec_walk;
915 	int c, i;
916 	int min_num_args = -1;
917 	int max_num_args = 0;
918 	int post_varargs = 0;
919 	zval *arg;
920 	int arg_count;
921 	zend_bool have_varargs = 0;
922 	zval **varargs = NULL;
923 	int *n_varargs = NULL;
924 
925 	for (spec_walk = type_spec; *spec_walk; spec_walk++) {
926 		c = *spec_walk;
927 		switch (c) {
928 			case 'l': case 'd':
929 			case 's': case 'b':
930 			case 'r': case 'a':
931 			case 'o': case 'O':
932 			case 'z': case 'Z':
933 			case 'C': case 'h':
934 			case 'f': case 'A':
935 			case 'H': case 'p':
936 			case 'S': case 'P':
937 			case 'L':
938 				max_num_args++;
939 				break;
940 
941 			case '|':
942 				min_num_args = max_num_args;
943 				break;
944 
945 			case '/':
946 			case '!':
947 				/* Pass */
948 				break;
949 
950 			case '*':
951 			case '+':
952 				if (have_varargs) {
953 					zend_parse_parameters_debug_error(
954 						"only one varargs specifier (* or +) is permitted");
955 					return FAILURE;
956 				}
957 				have_varargs = 1;
958 				/* we expect at least one parameter in varargs */
959 				if (c == '+') {
960 					max_num_args++;
961 				}
962 				/* mark the beginning of varargs */
963 				post_varargs = max_num_args;
964 				break;
965 
966 			default:
967 				zend_parse_parameters_debug_error("bad type specifier while parsing parameters");
968 				return FAILURE;
969 		}
970 	}
971 
972 	if (min_num_args < 0) {
973 		min_num_args = max_num_args;
974 	}
975 
976 	if (have_varargs) {
977 		/* calculate how many required args are at the end of the specifier list */
978 		post_varargs = max_num_args - post_varargs;
979 		max_num_args = -1;
980 	}
981 
982 	if (num_args < min_num_args || (num_args > max_num_args && max_num_args >= 0)) {
983 		if (!(flags & ZEND_PARSE_PARAMS_QUIET)) {
984 			zend_function *active_function = EG(current_execute_data)->func;
985 			const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
986 			zend_bool throw_exception = ZEND_ARG_USES_STRICT_TYPES() || (flags & ZEND_PARSE_PARAMS_THROW);
987 			zend_internal_argument_count_error(throw_exception, "%s%s%s() expects %s %d parameter%s, %d given",
988 					class_name,
989 					class_name[0] ? "::" : "",
990 					ZSTR_VAL(active_function->common.function_name),
991 					min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
992 					num_args < min_num_args ? min_num_args : max_num_args,
993 					(num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
994 					num_args);
995 		}
996 		return FAILURE;
997 	}
998 
999 	arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
1000 
1001 	if (num_args > arg_count) {
1002 		zend_parse_parameters_debug_error("could not obtain parameters for parsing");
1003 		return FAILURE;
1004 	}
1005 
1006 	i = 0;
1007 	while (num_args-- > 0) {
1008 		if (*type_spec == '|') {
1009 			type_spec++;
1010 		}
1011 
1012 		if (*type_spec == '*' || *type_spec == '+') {
1013 			int num_varargs = num_args + 1 - post_varargs;
1014 
1015 			/* eat up the passed in storage even if it won't be filled in with varargs */
1016 			varargs = va_arg(*va, zval **);
1017 			n_varargs = va_arg(*va, int *);
1018 			type_spec++;
1019 
1020 			if (num_varargs > 0) {
1021 				*n_varargs = num_varargs;
1022 				*varargs = ZEND_CALL_ARG(EG(current_execute_data), i + 1);
1023 				/* adjust how many args we have left and restart loop */
1024 				num_args += 1 - num_varargs;
1025 				i += num_varargs;
1026 				continue;
1027 			} else {
1028 				*varargs = NULL;
1029 				*n_varargs = 0;
1030 			}
1031 		}
1032 
1033 		arg = ZEND_CALL_ARG(EG(current_execute_data), i + 1);
1034 
1035 		if (zend_parse_arg(i+1, arg, va, &type_spec, flags) == FAILURE) {
1036 			/* clean up varargs array if it was used */
1037 			if (varargs && *varargs) {
1038 				*varargs = NULL;
1039 			}
1040 			return FAILURE;
1041 		}
1042 		i++;
1043 	}
1044 
1045 	return SUCCESS;
1046 }
1047 /* }}} */
1048 
zend_parse_parameters_ex(int flags, int num_args, const char *type_spec, ...)1049 ZEND_API int zend_parse_parameters_ex(int flags, int num_args, const char *type_spec, ...) /* {{{ */
1050 {
1051 	va_list va;
1052 	int retval;
1053 
1054 	va_start(va, type_spec);
1055 	retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1056 	va_end(va);
1057 
1058 	return retval;
1059 }
1060 /* }}} */
1061 
zend_parse_parameters(int num_args, const char *type_spec, ...)1062 ZEND_API int zend_parse_parameters(int num_args, const char *type_spec, ...) /* {{{ */
1063 {
1064 	va_list va;
1065 	int retval;
1066 	int flags = 0;
1067 
1068 	va_start(va, type_spec);
1069 	retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1070 	va_end(va);
1071 
1072 	return retval;
1073 }
1074 /* }}} */
1075 
zend_parse_parameters_throw(int num_args, const char *type_spec, ...)1076 ZEND_API int zend_parse_parameters_throw(int num_args, const char *type_spec, ...) /* {{{ */
1077 {
1078 	va_list va;
1079 	int retval;
1080 	int flags = ZEND_PARSE_PARAMS_THROW;
1081 
1082 	va_start(va, type_spec);
1083 	retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1084 	va_end(va);
1085 
1086 	return retval;
1087 }
1088 /* }}} */
1089 
zend_parse_method_parameters(int num_args, zval *this_ptr, const char *type_spec, ...)1090 ZEND_API int zend_parse_method_parameters(int num_args, zval *this_ptr, const char *type_spec, ...) /* {{{ */
1091 {
1092 	va_list va;
1093 	int retval;
1094 	int flags = 0;
1095 	const char *p = type_spec;
1096 	zval **object;
1097 	zend_class_entry *ce;
1098 
1099 	/* Just checking this_ptr is not enough, because fcall_common_helper does not set
1100 	 * Z_OBJ(EG(This)) to NULL when calling an internal function with common.scope == NULL.
1101 	 * In that case EG(This) would still be the $this from the calling code and we'd take the
1102 	 * wrong branch here. */
1103 	zend_bool is_method = EG(current_execute_data)->func->common.scope != NULL;
1104 
1105 	if (!is_method || !this_ptr || Z_TYPE_P(this_ptr) != IS_OBJECT) {
1106 		va_start(va, type_spec);
1107 		retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1108 		va_end(va);
1109 	} else {
1110 		p++;
1111 
1112 		va_start(va, type_spec);
1113 
1114 		object = va_arg(va, zval **);
1115 		ce = va_arg(va, zend_class_entry *);
1116 		*object = this_ptr;
1117 
1118 		if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce)) {
1119 			zend_error_noreturn(E_CORE_ERROR, "%s::%s() must be derived from %s::%s",
1120 				ZSTR_VAL(Z_OBJCE_P(this_ptr)->name), get_active_function_name(), ZSTR_VAL(ce->name), get_active_function_name());
1121 		}
1122 
1123 		retval = zend_parse_va_args(num_args, p, &va, flags);
1124 		va_end(va);
1125 	}
1126 	return retval;
1127 }
1128 /* }}} */
1129 
zend_parse_method_parameters_ex(int flags, int num_args, zval *this_ptr, const char *type_spec, ...)1130 ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args, zval *this_ptr, const char *type_spec, ...) /* {{{ */
1131 {
1132 	va_list va;
1133 	int retval;
1134 	const char *p = type_spec;
1135 	zval **object;
1136 	zend_class_entry *ce;
1137 
1138 	if (!this_ptr) {
1139 		va_start(va, type_spec);
1140 		retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1141 		va_end(va);
1142 	} else {
1143 		p++;
1144 		va_start(va, type_spec);
1145 
1146 		object = va_arg(va, zval **);
1147 		ce = va_arg(va, zend_class_entry *);
1148 		*object = this_ptr;
1149 
1150 		if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce)) {
1151 			if (!(flags & ZEND_PARSE_PARAMS_QUIET)) {
1152 				zend_error_noreturn(E_CORE_ERROR, "%s::%s() must be derived from %s::%s",
1153 					ZSTR_VAL(ce->name), get_active_function_name(), ZSTR_VAL(Z_OBJCE_P(this_ptr)->name), get_active_function_name());
1154 			}
1155 			va_end(va);
1156 			return FAILURE;
1157 		}
1158 
1159 		retval = zend_parse_va_args(num_args, p, &va, flags);
1160 		va_end(va);
1161 	}
1162 	return retval;
1163 }
1164 /* }}} */
1165 
1166 /* This function should be called after the constructor has been called
1167  * because it may call __set from the uninitialized object otherwise. */
zend_merge_properties(zval *obj, HashTable *properties)1168 ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */
1169 {
1170 	const zend_object_handlers *obj_ht = Z_OBJ_HT_P(obj);
1171 	zend_class_entry *old_scope = EG(fake_scope);
1172 	zend_string *key;
1173 	zval *value;
1174 
1175 	EG(fake_scope) = Z_OBJCE_P(obj);
1176 	ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, value) {
1177 		if (key) {
1178 			zval member;
1179 
1180 			ZVAL_STR(&member, key);
1181 			obj_ht->write_property(obj, &member, value, NULL);
1182 		}
1183 	} ZEND_HASH_FOREACH_END();
1184 	EG(fake_scope) = old_scope;
1185 }
1186 /* }}} */
1187 
zend_update_class_constants(zend_class_entry *class_type)1188 ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
1189 {
1190 	if (!(class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
1191 		zend_class_entry *ce;
1192 		zend_class_constant *c;
1193 		zval *val;
1194 		zend_property_info *prop_info;
1195 
1196 		if (class_type->parent) {
1197 			if (UNEXPECTED(zend_update_class_constants(class_type->parent) != SUCCESS)) {
1198 				return FAILURE;
1199 			}
1200 		}
1201 
1202 		ZEND_HASH_FOREACH_PTR(&class_type->constants_table, c) {
1203 			val = &c->value;
1204 			if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
1205 				if (UNEXPECTED(zval_update_constant_ex(val, c->ce) != SUCCESS)) {
1206 					return FAILURE;
1207 				}
1208 			}
1209 		} ZEND_HASH_FOREACH_END();
1210 
1211 		if (class_type->default_static_members_count && !CE_STATIC_MEMBERS(class_type)) {
1212 			if (class_type->type == ZEND_INTERNAL_CLASS || (class_type->ce_flags & (ZEND_ACC_IMMUTABLE|ZEND_ACC_PRELOADED))) {
1213 				zend_class_init_statics(class_type);
1214 			}
1215 		}
1216 
1217 		ce = class_type;
1218 		while (ce) {
1219 			ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
1220 				if (prop_info->ce == ce) {
1221 					if (prop_info->flags & ZEND_ACC_STATIC) {
1222 						val = CE_STATIC_MEMBERS(class_type) + prop_info->offset;
1223 					} else {
1224 						val = (zval*)((char*)class_type->default_properties_table + prop_info->offset - OBJ_PROP_TO_OFFSET(0));
1225 					}
1226 					if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
1227 						if (prop_info->type) {
1228 							zval tmp;
1229 
1230 							ZVAL_COPY(&tmp, val);
1231 							if (UNEXPECTED(zval_update_constant_ex(&tmp, ce) != SUCCESS)) {
1232 								zval_ptr_dtor(&tmp);
1233 								return FAILURE;
1234 							}
1235 							/* property initializers must always be evaluated with strict types */;
1236 							if (UNEXPECTED(!zend_verify_property_type(prop_info, &tmp, /* strict */ 1))) {
1237 								zval_ptr_dtor(&tmp);
1238 								return FAILURE;
1239 							}
1240 							zval_ptr_dtor(val);
1241 							ZVAL_COPY_VALUE(val, &tmp);
1242 						} else if (UNEXPECTED(zval_update_constant_ex(val, ce) != SUCCESS)) {
1243 							return FAILURE;
1244 						}
1245 					}
1246 				}
1247 			} ZEND_HASH_FOREACH_END();
1248 			ce = ce->parent;
1249 		}
1250 
1251 		class_type->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
1252 	}
1253 
1254 	return SUCCESS;
1255 }
1256 /* }}} */
1257 
_object_properties_init(zend_object *object, zend_class_entry *class_type)1258 static zend_always_inline void _object_properties_init(zend_object *object, zend_class_entry *class_type) /* {{{ */
1259 {
1260 	if (class_type->default_properties_count) {
1261 		zval *src = class_type->default_properties_table;
1262 		zval *dst = object->properties_table;
1263 		zval *end = src + class_type->default_properties_count;
1264 
1265 		if (UNEXPECTED(class_type->type == ZEND_INTERNAL_CLASS)) {
1266 			do {
1267 				ZVAL_COPY_OR_DUP_PROP(dst, src);
1268 				src++;
1269 				dst++;
1270 			} while (src != end);
1271 		} else {
1272 			do {
1273 				ZVAL_COPY_PROP(dst, src);
1274 				src++;
1275 				dst++;
1276 			} while (src != end);
1277 		}
1278 	}
1279 }
1280 /* }}} */
1281 
object_properties_init(zend_object *object, zend_class_entry *class_type)1282 ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type) /* {{{ */
1283 {
1284 	object->properties = NULL;
1285 	_object_properties_init(object, class_type);
1286 }
1287 /* }}} */
1288 
object_properties_init_ex(zend_object *object, HashTable *properties)1289 ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properties) /* {{{ */
1290 {
1291 	object->properties = properties;
1292 	if (object->ce->default_properties_count) {
1293 		zval *prop;
1294 		zend_string *key;
1295 		zend_property_info *property_info;
1296 
1297 		ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) {
1298 			property_info = zend_get_property_info(object->ce, key, 1);
1299 			if (property_info != ZEND_WRONG_PROPERTY_INFO &&
1300 			    property_info &&
1301 			    (property_info->flags & ZEND_ACC_STATIC) == 0) {
1302 				zval *slot = OBJ_PROP(object, property_info->offset);
1303 
1304 				if (UNEXPECTED(property_info->type)) {
1305 					zval tmp;
1306 
1307 					ZVAL_COPY_VALUE(&tmp, prop);
1308 					if (UNEXPECTED(!zend_verify_property_type(property_info, &tmp, 0))) {
1309 						continue;
1310 					}
1311 					ZVAL_COPY_VALUE(slot, &tmp);
1312 				} else {
1313 					ZVAL_COPY_VALUE(slot, prop);
1314 				}
1315 				ZVAL_INDIRECT(prop, slot);
1316 			}
1317 		} ZEND_HASH_FOREACH_END();
1318 	}
1319 }
1320 /* }}} */
1321 
object_properties_load(zend_object *object, HashTable *properties)1322 ZEND_API void object_properties_load(zend_object *object, HashTable *properties) /* {{{ */
1323 {
1324     zval *prop, tmp;
1325    	zend_string *key;
1326    	zend_long h;
1327    	zend_property_info *property_info;
1328 
1329    	ZEND_HASH_FOREACH_KEY_VAL(properties, h, key, prop) {
1330 		if (key) {
1331 			if (ZSTR_VAL(key)[0] == '\0') {
1332 				const char *class_name, *prop_name;
1333 				size_t prop_name_len;
1334 				if (zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_name_len) == SUCCESS) {
1335 					zend_string *pname = zend_string_init(prop_name, prop_name_len, 0);
1336 					zend_class_entry *prev_scope = EG(fake_scope);
1337 					if (class_name && class_name[0] != '*') {
1338 						zend_string *cname = zend_string_init(class_name, strlen(class_name), 0);
1339 						EG(fake_scope) = zend_lookup_class(cname);
1340 						zend_string_release_ex(cname, 0);
1341 					}
1342 					property_info = zend_get_property_info(object->ce, pname, 1);
1343 					zend_string_release_ex(pname, 0);
1344 					EG(fake_scope) = prev_scope;
1345 				} else {
1346 					property_info = ZEND_WRONG_PROPERTY_INFO;
1347 				}
1348 			} else {
1349 				property_info = zend_get_property_info(object->ce, key, 1);
1350 			}
1351 			if (property_info != ZEND_WRONG_PROPERTY_INFO &&
1352 				property_info &&
1353 				(property_info->flags & ZEND_ACC_STATIC) == 0) {
1354 				zval *slot = OBJ_PROP(object, property_info->offset);
1355 				zval_ptr_dtor(slot);
1356 				ZVAL_COPY_VALUE(slot, prop);
1357 				zval_add_ref(slot);
1358 				if (object->properties) {
1359 					ZVAL_INDIRECT(&tmp, slot);
1360 					zend_hash_update(object->properties, key, &tmp);
1361 				}
1362 			} else {
1363 				if (!object->properties) {
1364 					rebuild_object_properties(object);
1365 				}
1366 				prop = zend_hash_update(object->properties, key, prop);
1367 				zval_add_ref(prop);
1368 			}
1369 		} else {
1370 			if (!object->properties) {
1371 				rebuild_object_properties(object);
1372 			}
1373 			prop = zend_hash_index_update(object->properties, h, prop);
1374 			zval_add_ref(prop);
1375 		}
1376 	} ZEND_HASH_FOREACH_END();
1377 }
1378 /* }}} */
1379 
1380 /* This function requires 'properties' to contain all props declared in the
1381  * class and all props being public. If only a subset is given or the class
1382  * has protected members then you need to merge the properties separately by
1383  * calling zend_merge_properties(). */
_object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties)1384 static zend_always_inline int _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties) /* {{{ */
1385 {
1386 	if (UNEXPECTED(class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) {
1387 		if (class_type->ce_flags & ZEND_ACC_INTERFACE) {
1388 			zend_throw_error(NULL, "Cannot instantiate interface %s", ZSTR_VAL(class_type->name));
1389 		} else if (class_type->ce_flags & ZEND_ACC_TRAIT) {
1390 			zend_throw_error(NULL, "Cannot instantiate trait %s", ZSTR_VAL(class_type->name));
1391 		} else {
1392 			zend_throw_error(NULL, "Cannot instantiate abstract class %s", ZSTR_VAL(class_type->name));
1393 		}
1394 		ZVAL_NULL(arg);
1395 		Z_OBJ_P(arg) = NULL;
1396 		return FAILURE;
1397 	}
1398 
1399 	if (UNEXPECTED(!(class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
1400 		if (UNEXPECTED(zend_update_class_constants(class_type) != SUCCESS)) {
1401 			ZVAL_NULL(arg);
1402 			Z_OBJ_P(arg) = NULL;
1403 			return FAILURE;
1404 		}
1405 	}
1406 
1407 	if (class_type->create_object == NULL) {
1408 		zend_object *obj = zend_objects_new(class_type);
1409 
1410 		ZVAL_OBJ(arg, obj);
1411 		if (properties) {
1412 			object_properties_init_ex(obj, properties);
1413 		} else {
1414 			_object_properties_init(obj, class_type);
1415 		}
1416 	} else {
1417 		ZVAL_OBJ(arg, class_type->create_object(class_type));
1418 	}
1419 	return SUCCESS;
1420 }
1421 /* }}} */
1422 
object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties)1423 ZEND_API int object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties) /* {{{ */
1424 {
1425 	return _object_and_properties_init(arg, class_type, properties);
1426 }
1427 /* }}} */
1428 
object_init_ex(zval *arg, zend_class_entry *class_type)1429 ZEND_API int object_init_ex(zval *arg, zend_class_entry *class_type) /* {{{ */
1430 {
1431 	return _object_and_properties_init(arg, class_type, NULL);
1432 }
1433 /* }}} */
1434 
object_init(zval *arg)1435 ZEND_API int object_init(zval *arg) /* {{{ */
1436 {
1437 	ZVAL_OBJ(arg, zend_objects_new(zend_standard_class_def));
1438 	return SUCCESS;
1439 }
1440 /* }}} */
1441 
add_assoc_long_ex(zval *arg, const char *key, size_t key_len, zend_long n)1442 ZEND_API int add_assoc_long_ex(zval *arg, const char *key, size_t key_len, zend_long n) /* {{{ */
1443 {
1444 	zval tmp;
1445 
1446 	ZVAL_LONG(&tmp, n);
1447 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1448 	return SUCCESS;
1449 }
1450 /* }}} */
1451 
add_assoc_null_ex(zval *arg, const char *key, size_t key_len)1452 ZEND_API int add_assoc_null_ex(zval *arg, const char *key, size_t key_len) /* {{{ */
1453 {
1454 	zval tmp;
1455 
1456 	ZVAL_NULL(&tmp);
1457 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1458 	return SUCCESS;
1459 }
1460 /* }}} */
1461 
add_assoc_bool_ex(zval *arg, const char *key, size_t key_len, int b)1462 ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, size_t key_len, int b) /* {{{ */
1463 {
1464 	zval tmp;
1465 
1466 	ZVAL_BOOL(&tmp, b);
1467 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1468 	return SUCCESS;
1469 }
1470 /* }}} */
1471 
add_assoc_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r)1472 ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r) /* {{{ */
1473 {
1474 	zval tmp;
1475 
1476 	ZVAL_RES(&tmp, r);
1477 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1478 	return SUCCESS;
1479 }
1480 /* }}} */
1481 
add_assoc_double_ex(zval *arg, const char *key, size_t key_len, double d)1482 ZEND_API int add_assoc_double_ex(zval *arg, const char *key, size_t key_len, double d) /* {{{ */
1483 {
1484 	zval tmp;
1485 
1486 	ZVAL_DOUBLE(&tmp, d);
1487 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1488 	return SUCCESS;
1489 }
1490 /* }}} */
1491 
add_assoc_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str)1492 ZEND_API int add_assoc_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str) /* {{{ */
1493 {
1494 	zval tmp;
1495 
1496 	ZVAL_STR(&tmp, str);
1497 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1498 	return SUCCESS;
1499 }
1500 /* }}} */
1501 
add_assoc_string_ex(zval *arg, const char *key, size_t key_len, const char *str)1502 ZEND_API int add_assoc_string_ex(zval *arg, const char *key, size_t key_len, const char *str) /* {{{ */
1503 {
1504 	zval tmp;
1505 
1506 	ZVAL_STRING(&tmp, str);
1507 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1508 	return SUCCESS;
1509 }
1510 /* }}} */
1511 
add_assoc_stringl_ex(zval *arg, const char *key, size_t key_len, const char *str, size_t length)1512 ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, size_t key_len, const char *str, size_t length) /* {{{ */
1513 {
1514 	zval tmp;
1515 
1516 	ZVAL_STRINGL(&tmp, str, length);
1517 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1518 	return SUCCESS;
1519 }
1520 /* }}} */
1521 
add_assoc_zval_ex(zval *arg, const char *key, size_t key_len, zval *value)1522 ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, size_t key_len, zval *value) /* {{{ */
1523 {
1524 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, value);
1525 	return SUCCESS;
1526 }
1527 /* }}} */
1528 
add_index_long(zval *arg, zend_ulong index, zend_long n)1529 ZEND_API int add_index_long(zval *arg, zend_ulong index, zend_long n) /* {{{ */
1530 {
1531 	zval tmp;
1532 
1533 	ZVAL_LONG(&tmp, n);
1534 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1535 	return SUCCESS;
1536 }
1537 /* }}} */
1538 
add_index_null(zval *arg, zend_ulong index)1539 ZEND_API int add_index_null(zval *arg, zend_ulong index) /* {{{ */
1540 {
1541 	zval tmp;
1542 
1543 	ZVAL_NULL(&tmp);
1544 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1545 	return SUCCESS;
1546 }
1547 /* }}} */
1548 
add_index_bool(zval *arg, zend_ulong index, int b)1549 ZEND_API int add_index_bool(zval *arg, zend_ulong index, int b) /* {{{ */
1550 {
1551 	zval tmp;
1552 
1553 	ZVAL_BOOL(&tmp, b);
1554 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1555 	return SUCCESS;
1556 }
1557 /* }}} */
1558 
add_index_resource(zval *arg, zend_ulong index, zend_resource *r)1559 ZEND_API int add_index_resource(zval *arg, zend_ulong index, zend_resource *r) /* {{{ */
1560 {
1561 	zval tmp;
1562 
1563 	ZVAL_RES(&tmp, r);
1564 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1565 	return SUCCESS;
1566 }
1567 /* }}} */
1568 
add_index_double(zval *arg, zend_ulong index, double d)1569 ZEND_API int add_index_double(zval *arg, zend_ulong index, double d) /* {{{ */
1570 {
1571 	zval tmp;
1572 
1573 	ZVAL_DOUBLE(&tmp, d);
1574 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1575 	return SUCCESS;
1576 }
1577 /* }}} */
1578 
add_index_str(zval *arg, zend_ulong index, zend_string *str)1579 ZEND_API int add_index_str(zval *arg, zend_ulong index, zend_string *str) /* {{{ */
1580 {
1581 	zval tmp;
1582 
1583 	ZVAL_STR(&tmp, str);
1584 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1585 	return SUCCESS;
1586 }
1587 /* }}} */
1588 
add_index_string(zval *arg, zend_ulong index, const char *str)1589 ZEND_API int add_index_string(zval *arg, zend_ulong index, const char *str) /* {{{ */
1590 {
1591 	zval tmp;
1592 
1593 	ZVAL_STRING(&tmp, str);
1594 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1595 	return SUCCESS;
1596 }
1597 /* }}} */
1598 
add_index_stringl(zval *arg, zend_ulong index, const char *str, size_t length)1599 ZEND_API int add_index_stringl(zval *arg, zend_ulong index, const char *str, size_t length) /* {{{ */
1600 {
1601 	zval tmp;
1602 
1603 	ZVAL_STRINGL(&tmp, str, length);
1604 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1605 	return SUCCESS;
1606 }
1607 /* }}} */
1608 
add_next_index_long(zval *arg, zend_long n)1609 ZEND_API int add_next_index_long(zval *arg, zend_long n) /* {{{ */
1610 {
1611 	zval tmp;
1612 
1613 	ZVAL_LONG(&tmp, n);
1614 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1615 }
1616 /* }}} */
1617 
add_next_index_null(zval *arg)1618 ZEND_API int add_next_index_null(zval *arg) /* {{{ */
1619 {
1620 	zval tmp;
1621 
1622 	ZVAL_NULL(&tmp);
1623 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1624 }
1625 /* }}} */
1626 
add_next_index_bool(zval *arg, int b)1627 ZEND_API int add_next_index_bool(zval *arg, int b) /* {{{ */
1628 {
1629 	zval tmp;
1630 
1631 	ZVAL_BOOL(&tmp, b);
1632 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1633 }
1634 /* }}} */
1635 
add_next_index_resource(zval *arg, zend_resource *r)1636 ZEND_API int add_next_index_resource(zval *arg, zend_resource *r) /* {{{ */
1637 {
1638 	zval tmp;
1639 
1640 	ZVAL_RES(&tmp, r);
1641 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1642 }
1643 /* }}} */
1644 
add_next_index_double(zval *arg, double d)1645 ZEND_API int add_next_index_double(zval *arg, double d) /* {{{ */
1646 {
1647 	zval tmp;
1648 
1649 	ZVAL_DOUBLE(&tmp, d);
1650 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1651 }
1652 /* }}} */
1653 
add_next_index_str(zval *arg, zend_string *str)1654 ZEND_API int add_next_index_str(zval *arg, zend_string *str) /* {{{ */
1655 {
1656 	zval tmp;
1657 
1658 	ZVAL_STR(&tmp, str);
1659 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1660 }
1661 /* }}} */
1662 
add_next_index_string(zval *arg, const char *str)1663 ZEND_API int add_next_index_string(zval *arg, const char *str) /* {{{ */
1664 {
1665 	zval tmp;
1666 
1667 	ZVAL_STRING(&tmp, str);
1668 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1669 }
1670 /* }}} */
1671 
add_next_index_stringl(zval *arg, const char *str, size_t length)1672 ZEND_API int add_next_index_stringl(zval *arg, const char *str, size_t length) /* {{{ */
1673 {
1674 	zval tmp;
1675 
1676 	ZVAL_STRINGL(&tmp, str, length);
1677 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1678 }
1679 /* }}} */
1680 
array_set_zval_key(HashTable *ht, zval *key, zval *value)1681 ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */
1682 {
1683 	zval *result;
1684 
1685 	switch (Z_TYPE_P(key)) {
1686 		case IS_STRING:
1687 			result = zend_symtable_update(ht, Z_STR_P(key), value);
1688 			break;
1689 		case IS_NULL:
1690 			result = zend_symtable_update(ht, ZSTR_EMPTY_ALLOC(), value);
1691 			break;
1692 		case IS_RESOURCE:
1693 			zend_error(E_NOTICE, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(key), Z_RES_HANDLE_P(key));
1694 			result = zend_hash_index_update(ht, Z_RES_HANDLE_P(key), value);
1695 			break;
1696 		case IS_FALSE:
1697 			result = zend_hash_index_update(ht, 0, value);
1698 			break;
1699 		case IS_TRUE:
1700 			result = zend_hash_index_update(ht, 1, value);
1701 			break;
1702 		case IS_LONG:
1703 			result = zend_hash_index_update(ht, Z_LVAL_P(key), value);
1704 			break;
1705 		case IS_DOUBLE:
1706 			result = zend_hash_index_update(ht, zend_dval_to_lval(Z_DVAL_P(key)), value);
1707 			break;
1708 		default:
1709 			zend_error(E_WARNING, "Illegal offset type");
1710 			result = NULL;
1711 	}
1712 
1713 	if (result) {
1714 		Z_TRY_ADDREF_P(result);
1715 		return SUCCESS;
1716 	} else {
1717 		return FAILURE;
1718 	}
1719 }
1720 /* }}} */
1721 
add_property_long_ex(zval *arg, const char *key, size_t key_len, zend_long n)1722 ZEND_API int add_property_long_ex(zval *arg, const char *key, size_t key_len, zend_long n) /* {{{ */
1723 {
1724 	zval tmp;
1725 
1726 	ZVAL_LONG(&tmp, n);
1727 	return add_property_zval_ex(arg, key, key_len, &tmp);
1728 }
1729 /* }}} */
1730 
add_property_bool_ex(zval *arg, const char *key, size_t key_len, zend_long b)1731 ZEND_API int add_property_bool_ex(zval *arg, const char *key, size_t key_len, zend_long b) /* {{{ */
1732 {
1733 	zval tmp;
1734 
1735 	ZVAL_BOOL(&tmp, b);
1736 	return add_property_zval_ex(arg, key, key_len, &tmp);
1737 }
1738 /* }}} */
1739 
add_property_null_ex(zval *arg, const char *key, size_t key_len)1740 ZEND_API int add_property_null_ex(zval *arg, const char *key, size_t key_len) /* {{{ */
1741 {
1742 	zval tmp;
1743 
1744 	ZVAL_NULL(&tmp);
1745 	return add_property_zval_ex(arg, key, key_len, &tmp);
1746 }
1747 /* }}} */
1748 
add_property_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r)1749 ZEND_API int add_property_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r) /* {{{ */
1750 {
1751 	zval tmp;
1752 
1753 	ZVAL_RES(&tmp, r);
1754 	add_property_zval_ex(arg, key, key_len, &tmp);
1755 	zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1756 	return SUCCESS;
1757 }
1758 /* }}} */
1759 
add_property_double_ex(zval *arg, const char *key, size_t key_len, double d)1760 ZEND_API int add_property_double_ex(zval *arg, const char *key, size_t key_len, double d) /* {{{ */
1761 {
1762 	zval tmp;
1763 
1764 	ZVAL_DOUBLE(&tmp, d);
1765 	return add_property_zval_ex(arg, key, key_len, &tmp);
1766 }
1767 /* }}} */
1768 
add_property_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str)1769 ZEND_API int add_property_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str) /* {{{ */
1770 {
1771 	zval tmp;
1772 
1773 	ZVAL_STR(&tmp, str);
1774 	add_property_zval_ex(arg, key, key_len, &tmp);
1775 	zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1776 	return SUCCESS;
1777 }
1778 /* }}} */
1779 
add_property_string_ex(zval *arg, const char *key, size_t key_len, const char *str)1780 ZEND_API int add_property_string_ex(zval *arg, const char *key, size_t key_len, const char *str) /* {{{ */
1781 {
1782 	zval tmp;
1783 
1784 	ZVAL_STRING(&tmp, str);
1785 	add_property_zval_ex(arg, key, key_len, &tmp);
1786 	zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1787 	return SUCCESS;
1788 }
1789 /* }}} */
1790 
add_property_stringl_ex(zval *arg, const char *key, size_t key_len, const char *str, size_t length)1791 ZEND_API int add_property_stringl_ex(zval *arg, const char *key, size_t key_len, const char *str, size_t length) /* {{{ */
1792 {
1793 	zval tmp;
1794 
1795 	ZVAL_STRINGL(&tmp, str, length);
1796 	add_property_zval_ex(arg, key, key_len, &tmp);
1797 	zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1798 	return SUCCESS;
1799 }
1800 /* }}} */
1801 
add_property_zval_ex(zval *arg, const char *key, size_t key_len, zval *value)1802 ZEND_API int add_property_zval_ex(zval *arg, const char *key, size_t key_len, zval *value) /* {{{ */
1803 {
1804 	zval z_key;
1805 
1806 	ZVAL_STRINGL(&z_key, key, key_len);
1807 	Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, value, NULL);
1808 	zval_ptr_dtor(&z_key);
1809 	return SUCCESS;
1810 }
1811 /* }}} */
1812 
zend_startup_module_ex(zend_module_entry *module)1813 ZEND_API int zend_startup_module_ex(zend_module_entry *module) /* {{{ */
1814 {
1815 	size_t name_len;
1816 	zend_string *lcname;
1817 
1818 	if (module->module_started) {
1819 		return SUCCESS;
1820 	}
1821 	module->module_started = 1;
1822 
1823 	/* Check module dependencies */
1824 	if (module->deps) {
1825 		const zend_module_dep *dep = module->deps;
1826 
1827 		while (dep->name) {
1828 			if (dep->type == MODULE_DEP_REQUIRED) {
1829 				zend_module_entry *req_mod;
1830 
1831 				name_len = strlen(dep->name);
1832 				lcname = zend_string_alloc(name_len, 0);
1833 				zend_str_tolower_copy(ZSTR_VAL(lcname), dep->name, name_len);
1834 
1835 				if ((req_mod = zend_hash_find_ptr(&module_registry, lcname)) == NULL || !req_mod->module_started) {
1836 					zend_string_efree(lcname);
1837 					/* TODO: Check version relationship */
1838 					zend_error(E_CORE_WARNING, "Cannot load module '%s' because required module '%s' is not loaded", module->name, dep->name);
1839 					module->module_started = 0;
1840 					return FAILURE;
1841 				}
1842 				zend_string_efree(lcname);
1843 			}
1844 			++dep;
1845 		}
1846 	}
1847 
1848 	/* Initialize module globals */
1849 	if (module->globals_size) {
1850 #ifdef ZTS
1851 		ts_allocate_id(module->globals_id_ptr, module->globals_size, (ts_allocate_ctor) module->globals_ctor, (ts_allocate_dtor) module->globals_dtor);
1852 #else
1853 		if (module->globals_ctor) {
1854 			module->globals_ctor(module->globals_ptr);
1855 		}
1856 #endif
1857 	}
1858 	if (module->module_startup_func) {
1859 		EG(current_module) = module;
1860 		if (module->module_startup_func(module->type, module->module_number)==FAILURE) {
1861 			zend_error_noreturn(E_CORE_ERROR,"Unable to start %s module", module->name);
1862 			EG(current_module) = NULL;
1863 			return FAILURE;
1864 		}
1865 		EG(current_module) = NULL;
1866 	}
1867 	return SUCCESS;
1868 }
1869 /* }}} */
1870 
zend_startup_module_zval(zval *zv)1871 static int zend_startup_module_zval(zval *zv) /* {{{ */
1872 {
1873 	zend_module_entry *module = Z_PTR_P(zv);
1874 
1875 	return (zend_startup_module_ex(module) == SUCCESS) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
1876 }
1877 /* }}} */
1878 
zend_sort_modules(void *base, size_t count, size_t siz, compare_func_t compare, swap_func_t swp)1879 static void zend_sort_modules(void *base, size_t count, size_t siz, compare_func_t compare, swap_func_t swp) /* {{{ */
1880 {
1881 	Bucket *b1 = base;
1882 	Bucket *b2;
1883 	Bucket *end = b1 + count;
1884 	Bucket tmp;
1885 	zend_module_entry *m, *r;
1886 
1887 	while (b1 < end) {
1888 try_again:
1889 		m = (zend_module_entry*)Z_PTR(b1->val);
1890 		if (!m->module_started && m->deps) {
1891 			const zend_module_dep *dep = m->deps;
1892 			while (dep->name) {
1893 				if (dep->type == MODULE_DEP_REQUIRED || dep->type == MODULE_DEP_OPTIONAL) {
1894 					b2 = b1 + 1;
1895 					while (b2 < end) {
1896 						r = (zend_module_entry*)Z_PTR(b2->val);
1897 						if (strcasecmp(dep->name, r->name) == 0) {
1898 							tmp = *b1;
1899 							*b1 = *b2;
1900 							*b2 = tmp;
1901 							goto try_again;
1902 						}
1903 						b2++;
1904 					}
1905 				}
1906 				dep++;
1907 			}
1908 		}
1909 		b1++;
1910 	}
1911 }
1912 /* }}} */
1913 
zend_collect_module_handlers(void)1914 ZEND_API void zend_collect_module_handlers(void) /* {{{ */
1915 {
1916 	zend_module_entry *module;
1917 	int startup_count = 0;
1918 	int shutdown_count = 0;
1919 	int post_deactivate_count = 0;
1920 	zend_class_entry *ce;
1921 	int class_count = 0;
1922 
1923 	/* Collect extensions with request startup/shutdown handlers */
1924 	ZEND_HASH_FOREACH_PTR(&module_registry, module) {
1925 		if (module->request_startup_func) {
1926 			startup_count++;
1927 		}
1928 		if (module->request_shutdown_func) {
1929 			shutdown_count++;
1930 		}
1931 		if (module->post_deactivate_func) {
1932 			post_deactivate_count++;
1933 		}
1934 	} ZEND_HASH_FOREACH_END();
1935 	module_request_startup_handlers = (zend_module_entry**)malloc(
1936 	    sizeof(zend_module_entry*) *
1937 		(startup_count + 1 +
1938 		 shutdown_count + 1 +
1939 		 post_deactivate_count + 1));
1940 	module_request_startup_handlers[startup_count] = NULL;
1941 	module_request_shutdown_handlers = module_request_startup_handlers + startup_count + 1;
1942 	module_request_shutdown_handlers[shutdown_count] = NULL;
1943 	module_post_deactivate_handlers = module_request_shutdown_handlers + shutdown_count + 1;
1944 	module_post_deactivate_handlers[post_deactivate_count] = NULL;
1945 	startup_count = 0;
1946 
1947 	ZEND_HASH_FOREACH_PTR(&module_registry, module) {
1948 		if (module->request_startup_func) {
1949 			module_request_startup_handlers[startup_count++] = module;
1950 		}
1951 		if (module->request_shutdown_func) {
1952 			module_request_shutdown_handlers[--shutdown_count] = module;
1953 		}
1954 		if (module->post_deactivate_func) {
1955 			module_post_deactivate_handlers[--post_deactivate_count] = module;
1956 		}
1957 	} ZEND_HASH_FOREACH_END();
1958 
1959 	/* Collect internal classes with static members */
1960 	ZEND_HASH_FOREACH_PTR(CG(class_table), ce) {
1961 		if (ce->type == ZEND_INTERNAL_CLASS &&
1962 		    ce->default_static_members_count > 0) {
1963 		    class_count++;
1964 		}
1965 	} ZEND_HASH_FOREACH_END();
1966 
1967 	class_cleanup_handlers = (zend_class_entry**)malloc(
1968 		sizeof(zend_class_entry*) *
1969 		(class_count + 1));
1970 	class_cleanup_handlers[class_count] = NULL;
1971 
1972 	if (class_count) {
1973 		ZEND_HASH_FOREACH_PTR(CG(class_table), ce) {
1974 			if (ce->type == ZEND_INTERNAL_CLASS &&
1975 			    ce->default_static_members_count > 0) {
1976 			    class_cleanup_handlers[--class_count] = ce;
1977 			}
1978 		} ZEND_HASH_FOREACH_END();
1979 	}
1980 }
1981 /* }}} */
1982 
zend_startup_modules(void)1983 ZEND_API int zend_startup_modules(void) /* {{{ */
1984 {
1985 	zend_hash_sort_ex(&module_registry, zend_sort_modules, NULL, 0);
1986 	zend_hash_apply(&module_registry, zend_startup_module_zval);
1987 	return SUCCESS;
1988 }
1989 /* }}} */
1990 
zend_destroy_modules(void)1991 ZEND_API void zend_destroy_modules(void) /* {{{ */
1992 {
1993 	free(class_cleanup_handlers);
1994 	free(module_request_startup_handlers);
1995 	zend_hash_graceful_reverse_destroy(&module_registry);
1996 }
1997 /* }}} */
1998 
zend_register_module_ex(zend_module_entry *module)1999 ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module) /* {{{ */
2000 {
2001 	size_t name_len;
2002 	zend_string *lcname;
2003 	zend_module_entry *module_ptr;
2004 
2005 	if (!module) {
2006 		return NULL;
2007 	}
2008 
2009 #if 0
2010 	zend_printf("%s: Registering module %d\n", module->name, module->module_number);
2011 #endif
2012 
2013 	/* Check module dependencies */
2014 	if (module->deps) {
2015 		const zend_module_dep *dep = module->deps;
2016 
2017 		while (dep->name) {
2018 			if (dep->type == MODULE_DEP_CONFLICTS) {
2019 				name_len = strlen(dep->name);
2020 				lcname = zend_string_alloc(name_len, 0);
2021 				zend_str_tolower_copy(ZSTR_VAL(lcname), dep->name, name_len);
2022 
2023 				if (zend_hash_exists(&module_registry, lcname) || zend_get_extension(dep->name)) {
2024 					zend_string_efree(lcname);
2025 					/* TODO: Check version relationship */
2026 					zend_error(E_CORE_WARNING, "Cannot load module '%s' because conflicting module '%s' is already loaded", module->name, dep->name);
2027 					return NULL;
2028 				}
2029 				zend_string_efree(lcname);
2030 			}
2031 			++dep;
2032 		}
2033 	}
2034 
2035 	name_len = strlen(module->name);
2036 	lcname = zend_string_alloc(name_len, module->type == MODULE_PERSISTENT);
2037 	zend_str_tolower_copy(ZSTR_VAL(lcname), module->name, name_len);
2038 
2039 	lcname = zend_new_interned_string(lcname);
2040 	if ((module_ptr = zend_hash_add_mem(&module_registry, lcname, module, sizeof(zend_module_entry))) == NULL) {
2041 		zend_error(E_CORE_WARNING, "Module '%s' already loaded", module->name);
2042 		zend_string_release(lcname);
2043 		return NULL;
2044 	}
2045 	module = module_ptr;
2046 	EG(current_module) = module;
2047 
2048 	if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type)==FAILURE) {
2049 		zend_hash_del(&module_registry, lcname);
2050 		zend_string_release(lcname);
2051 		EG(current_module) = NULL;
2052 		zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name);
2053 		return NULL;
2054 	}
2055 
2056 	EG(current_module) = NULL;
2057 	zend_string_release(lcname);
2058 	return module;
2059 }
2060 /* }}} */
2061 
zend_register_internal_module(zend_module_entry *module)2062 ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *module) /* {{{ */
2063 {
2064 	module->module_number = zend_next_free_module();
2065 	module->type = MODULE_PERSISTENT;
2066 	return zend_register_module_ex(module);
2067 }
2068 /* }}} */
2069 
zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, int error_type)2070 ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, int error_type) /* {{{ */
2071 {
2072 	char lcname[16];
2073 	size_t name_len;
2074 
2075 	if (ZSTR_VAL(fptr->common.function_name)[0] != '_'
2076 	 || ZSTR_VAL(fptr->common.function_name)[1] != '_') {
2077 		return;
2078 	}
2079 
2080 	/* we don't care if the function name is longer, in fact lowercasing only
2081 	 * the beginning of the name speeds up the check process */
2082 	name_len = ZSTR_LEN(fptr->common.function_name);
2083 	zend_str_tolower_copy(lcname, ZSTR_VAL(fptr->common.function_name), MIN(name_len, sizeof(lcname)-1));
2084 	lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
2085 
2086 	if (name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1) && fptr->common.num_args != 0) {
2087 		zend_error(error_type, "Destructor %s::%s() cannot take arguments", ZSTR_VAL(ce->name), ZEND_DESTRUCTOR_FUNC_NAME);
2088 	} else if (name_len == sizeof(ZEND_CLONE_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME) - 1) && fptr->common.num_args != 0) {
2089 		zend_error(error_type, "Method %s::%s() cannot accept any arguments", ZSTR_VAL(ce->name), ZEND_CLONE_FUNC_NAME);
2090 	} else if (name_len == sizeof(ZEND_GET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME) - 1)) {
2091 		if (fptr->common.num_args != 1) {
2092 			zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ZSTR_VAL(ce->name), ZEND_GET_FUNC_NAME);
2093 		} else if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
2094 			zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ZSTR_VAL(ce->name), ZEND_GET_FUNC_NAME);
2095 		}
2096 	} else if (name_len == sizeof(ZEND_SET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME) - 1)) {
2097 		if (fptr->common.num_args != 2) {
2098 			zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ZSTR_VAL(ce->name), ZEND_SET_FUNC_NAME);
2099 		} else if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
2100 			zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ZSTR_VAL(ce->name), ZEND_SET_FUNC_NAME);
2101 		}
2102 	} else if (name_len == sizeof(ZEND_UNSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME) - 1)) {
2103 		if (fptr->common.num_args != 1) {
2104 			zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ZSTR_VAL(ce->name), ZEND_UNSET_FUNC_NAME);
2105 		} else if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
2106 			zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ZSTR_VAL(ce->name), ZEND_UNSET_FUNC_NAME);
2107 		}
2108 	} else if (name_len == sizeof(ZEND_ISSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME) - 1)) {
2109 		if (fptr->common.num_args != 1) {
2110 			zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ZSTR_VAL(ce->name), ZEND_ISSET_FUNC_NAME);
2111 		} else if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
2112 			zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ZSTR_VAL(ce->name), ZEND_ISSET_FUNC_NAME);
2113 		}
2114 	} else if (name_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME) - 1)) {
2115 		if (fptr->common.num_args != 2) {
2116 			zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ZSTR_VAL(ce->name), ZEND_CALL_FUNC_NAME);
2117 		} else if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
2118 			zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ZSTR_VAL(ce->name), ZEND_CALL_FUNC_NAME);
2119 		}
2120 	} else if (name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1 &&
2121 		!memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1)
2122 	) {
2123 		if (fptr->common.num_args != 2) {
2124 			zend_error(error_type, "Method %s::__callStatic() must take exactly 2 arguments", ZSTR_VAL(ce->name));
2125 		} else if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
2126 			zend_error(error_type, "Method %s::__callStatic() cannot take arguments by reference", ZSTR_VAL(ce->name));
2127 		}
2128  	} else if (name_len == sizeof(ZEND_TOSTRING_FUNC_NAME) - 1 &&
2129  		!memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && fptr->common.num_args != 0
2130 	) {
2131 		zend_error(error_type, "Method %s::%s() cannot take arguments", ZSTR_VAL(ce->name), ZEND_TOSTRING_FUNC_NAME);
2132 	} else if (name_len == sizeof(ZEND_DEBUGINFO_FUNC_NAME) - 1 &&
2133 		!memcmp(lcname, ZEND_DEBUGINFO_FUNC_NAME, sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1) && fptr->common.num_args != 0) {
2134 		zend_error(error_type, "Method %s::%s() cannot take arguments", ZSTR_VAL(ce->name), ZEND_DEBUGINFO_FUNC_NAME);
2135 	}
2136 }
2137 /* }}} */
2138 
2139 /* registers all functions in *library_functions in the function hash */
zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type)2140 ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type) /* {{{ */
2141 {
2142 	const zend_function_entry *ptr = functions;
2143 	zend_function function, *reg_function;
2144 	zend_internal_function *internal_function = (zend_internal_function *)&function;
2145 	int count=0, unload=0;
2146 	HashTable *target_function_table = function_table;
2147 	int error_type;
2148 	zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__callstatic = NULL, *__tostring = NULL, *__debugInfo = NULL, *serialize_func = NULL, *unserialize_func = NULL;
2149 	zend_string *lowercase_name;
2150 	size_t fname_len;
2151 	const char *lc_class_name = NULL;
2152 	size_t class_name_len = 0;
2153 
2154 	if (type==MODULE_PERSISTENT) {
2155 		error_type = E_CORE_WARNING;
2156 	} else {
2157 		error_type = E_WARNING;
2158 	}
2159 
2160 	if (!target_function_table) {
2161 		target_function_table = CG(function_table);
2162 	}
2163 	internal_function->type = ZEND_INTERNAL_FUNCTION;
2164 	internal_function->module = EG(current_module);
2165 	memset(internal_function->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
2166 
2167 	if (scope) {
2168 		class_name_len = ZSTR_LEN(scope->name);
2169 		if ((lc_class_name = zend_memrchr(ZSTR_VAL(scope->name), '\\', class_name_len))) {
2170 			++lc_class_name;
2171 			class_name_len -= (lc_class_name - ZSTR_VAL(scope->name));
2172 			lc_class_name = zend_str_tolower_dup(lc_class_name, class_name_len);
2173 		} else {
2174 			lc_class_name = zend_str_tolower_dup(ZSTR_VAL(scope->name), class_name_len);
2175 		}
2176 	}
2177 
2178 	while (ptr->fname) {
2179 		fname_len = strlen(ptr->fname);
2180 		internal_function->handler = ptr->handler;
2181 		internal_function->function_name = zend_string_init_interned(ptr->fname, fname_len, 1);
2182 		internal_function->scope = scope;
2183 		internal_function->prototype = NULL;
2184 		if (ptr->flags) {
2185 			if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
2186 				if (ptr->flags != ZEND_ACC_DEPRECATED && scope) {
2187 					zend_error(error_type, "Invalid access level for %s%s%s() - access must be exactly one of public, protected or private", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2188 				}
2189 				internal_function->fn_flags = ZEND_ACC_PUBLIC | ptr->flags;
2190 			} else {
2191 				internal_function->fn_flags = ptr->flags;
2192 			}
2193 		} else {
2194 			internal_function->fn_flags = ZEND_ACC_PUBLIC;
2195 		}
2196 		if (ptr->arg_info) {
2197 			zend_internal_function_info *info = (zend_internal_function_info*)ptr->arg_info;
2198 
2199 			internal_function->arg_info = (zend_internal_arg_info*)ptr->arg_info+1;
2200 			internal_function->num_args = ptr->num_args;
2201 			/* Currently you cannot denote that the function can accept less arguments than num_args */
2202 			if (info->required_num_args == (zend_uintptr_t)-1) {
2203 				internal_function->required_num_args = ptr->num_args;
2204 			} else {
2205 				internal_function->required_num_args = info->required_num_args;
2206 			}
2207 			if (info->return_reference) {
2208 				internal_function->fn_flags |= ZEND_ACC_RETURN_REFERENCE;
2209 			}
2210 			if (ptr->arg_info[ptr->num_args].is_variadic) {
2211 				internal_function->fn_flags |= ZEND_ACC_VARIADIC;
2212 				/* Don't count the variadic argument */
2213 				internal_function->num_args--;
2214 			}
2215 			if (ZEND_TYPE_IS_SET(info->type)) {
2216 				if (ZEND_TYPE_IS_CLASS(info->type)) {
2217 					const char *type_name = (const char*)info->type;
2218 
2219 					if (type_name[0] == '?') {
2220 						type_name++;
2221 					}
2222 					if (!scope && (!strcasecmp(type_name, "self") || !strcasecmp(type_name, "parent"))) {
2223 						zend_error_noreturn(E_CORE_ERROR, "Cannot declare a return type of %s outside of a class scope", type_name);
2224 					}
2225 				}
2226 
2227 				internal_function->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
2228 			}
2229 		} else {
2230 			internal_function->arg_info = NULL;
2231 			internal_function->num_args = 0;
2232 			internal_function->required_num_args = 0;
2233 		}
2234 		zend_set_function_arg_flags((zend_function*)internal_function);
2235 		if (ptr->flags & ZEND_ACC_ABSTRACT) {
2236 			if (scope) {
2237 				/* This is a class that must be abstract itself. Here we set the check info. */
2238 				scope->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
2239 				if (!(scope->ce_flags & ZEND_ACC_INTERFACE)) {
2240 					/* Since the class is not an interface it needs to be declared as a abstract class. */
2241 					/* Since here we are handling internal functions only we can add the keyword flag. */
2242 					/* This time we set the flag for the keyword 'abstract'. */
2243 					scope->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
2244 				}
2245 			}
2246 			if (ptr->flags & ZEND_ACC_STATIC && (!scope || !(scope->ce_flags & ZEND_ACC_INTERFACE))) {
2247 				zend_error(error_type, "Static function %s%s%s() cannot be abstract", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2248 			}
2249 		} else {
2250 			if (scope && (scope->ce_flags & ZEND_ACC_INTERFACE)) {
2251 				efree((char*)lc_class_name);
2252 				zend_error(error_type, "Interface %s cannot contain non abstract method %s()", ZSTR_VAL(scope->name), ptr->fname);
2253 				return FAILURE;
2254 			}
2255 			if (!internal_function->handler) {
2256 				if (scope) {
2257 					efree((char*)lc_class_name);
2258 				}
2259 				zend_error(error_type, "Method %s%s%s() cannot be a NULL function", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2260 				zend_unregister_functions(functions, count, target_function_table);
2261 				return FAILURE;
2262 			}
2263 		}
2264 		lowercase_name = zend_string_tolower_ex(internal_function->function_name, type == MODULE_PERSISTENT);
2265 		lowercase_name = zend_new_interned_string(lowercase_name);
2266 		reg_function = malloc(sizeof(zend_internal_function));
2267 		memcpy(reg_function, &function, sizeof(zend_internal_function));
2268 		if (zend_hash_add_ptr(target_function_table, lowercase_name, reg_function) == NULL) {
2269 			unload=1;
2270 			free(reg_function);
2271 			zend_string_release(lowercase_name);
2272 			break;
2273 		}
2274 
2275 		/* If types of arguments have to be checked */
2276 		if (reg_function->common.arg_info && reg_function->common.num_args) {
2277 			uint32_t i;
2278 			for (i = 0; i < reg_function->common.num_args; i++) {
2279 				if (ZEND_TYPE_IS_SET(reg_function->common.arg_info[i].type)) {
2280 				    reg_function->common.fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
2281 					break;
2282 				}
2283 			}
2284 		}
2285 
2286 		if (reg_function->common.arg_info &&
2287 		    (reg_function->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS))) {
2288 			/* convert "const char*" class type names into "zend_string*" */
2289 			uint32_t i;
2290 			uint32_t num_args = reg_function->common.num_args + 1;
2291 			zend_arg_info *arg_info = reg_function->common.arg_info - 1;
2292 			zend_arg_info *new_arg_info;
2293 
2294 			if (reg_function->common.fn_flags & ZEND_ACC_VARIADIC) {
2295 				num_args++;
2296 			}
2297 			new_arg_info = malloc(sizeof(zend_arg_info) * num_args);
2298 			memcpy(new_arg_info, arg_info, sizeof(zend_arg_info) * num_args);
2299 			reg_function->common.arg_info = new_arg_info + 1;
2300 			for (i = 0; i < num_args; i++) {
2301 				if (ZEND_TYPE_IS_CLASS(new_arg_info[i].type)) {
2302 					const char *class_name = (const char*)new_arg_info[i].type;
2303 					zend_bool allow_null = 0;
2304 					zend_string *str;
2305 
2306 					if (class_name[0] == '?') {
2307 						class_name++;
2308 						allow_null = 1;
2309 					}
2310 					str = zend_string_init_interned(class_name, strlen(class_name), 1);
2311 					new_arg_info[i].type = ZEND_TYPE_ENCODE_CLASS(str, allow_null);
2312 				}
2313 			}
2314 		}
2315 
2316 		if (scope) {
2317 			/* Look for ctor, dtor, clone
2318 			 * If it's an old-style constructor, store it only if we don't have
2319 			 * a constructor already.
2320 			 */
2321 			if ((fname_len == class_name_len) && !ctor && !memcmp(ZSTR_VAL(lowercase_name), lc_class_name, class_name_len+1)) {
2322 				ctor = reg_function;
2323 			} else if (zend_string_equals_literal(lowercase_name, "serialize")) {
2324 				serialize_func = reg_function;
2325 			} else if (zend_string_equals_literal(lowercase_name, "unserialize")) {
2326 				unserialize_func = reg_function;
2327 			} else if (ZSTR_VAL(lowercase_name)[0] != '_' || ZSTR_VAL(lowercase_name)[1] != '_') {
2328 				reg_function = NULL;
2329 			} else if (zend_string_equals_literal(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME)) {
2330 				ctor = reg_function;
2331 			} else if (zend_string_equals_literal(lowercase_name, ZEND_DESTRUCTOR_FUNC_NAME)) {
2332 				dtor = reg_function;
2333 				if (internal_function->num_args) {
2334 					zend_error(error_type, "Destructor %s::%s() cannot take arguments", ZSTR_VAL(scope->name), ptr->fname);
2335 				}
2336 			} else if (zend_string_equals_literal(lowercase_name, ZEND_CLONE_FUNC_NAME)) {
2337 				clone = reg_function;
2338 			} else if (zend_string_equals_literal(lowercase_name, ZEND_CALL_FUNC_NAME)) {
2339 				__call = reg_function;
2340 			} else if (zend_string_equals_literal(lowercase_name, ZEND_CALLSTATIC_FUNC_NAME)) {
2341 				__callstatic = reg_function;
2342 			} else if (zend_string_equals_literal(lowercase_name, ZEND_TOSTRING_FUNC_NAME)) {
2343 				__tostring = reg_function;
2344 			} else if (zend_string_equals_literal(lowercase_name, ZEND_GET_FUNC_NAME)) {
2345 				__get = reg_function;
2346 				scope->ce_flags |= ZEND_ACC_USE_GUARDS;
2347 			} else if (zend_string_equals_literal(lowercase_name, ZEND_SET_FUNC_NAME)) {
2348 				__set = reg_function;
2349 				scope->ce_flags |= ZEND_ACC_USE_GUARDS;
2350 			} else if (zend_string_equals_literal(lowercase_name, ZEND_UNSET_FUNC_NAME)) {
2351 				__unset = reg_function;
2352 				scope->ce_flags |= ZEND_ACC_USE_GUARDS;
2353 			} else if (zend_string_equals_literal(lowercase_name, ZEND_ISSET_FUNC_NAME)) {
2354 				__isset = reg_function;
2355 				scope->ce_flags |= ZEND_ACC_USE_GUARDS;
2356 			} else if (zend_string_equals_literal(lowercase_name, ZEND_DEBUGINFO_FUNC_NAME)) {
2357 				__debugInfo = reg_function;
2358 			} else {
2359 				reg_function = NULL;
2360 			}
2361 			if (reg_function) {
2362 				zend_check_magic_method_implementation(scope, reg_function, error_type);
2363 			}
2364 		}
2365 		ptr++;
2366 		count++;
2367 		zend_string_release(lowercase_name);
2368 	}
2369 	if (unload) { /* before unloading, display all remaining bad function in the module */
2370 		if (scope) {
2371 			efree((char*)lc_class_name);
2372 		}
2373 		while (ptr->fname) {
2374 			fname_len = strlen(ptr->fname);
2375 			lowercase_name = zend_string_alloc(fname_len, 0);
2376 			zend_str_tolower_copy(ZSTR_VAL(lowercase_name), ptr->fname, fname_len);
2377 			if (zend_hash_exists(target_function_table, lowercase_name)) {
2378 				zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2379 			}
2380 			zend_string_efree(lowercase_name);
2381 			ptr++;
2382 		}
2383 		zend_unregister_functions(functions, count, target_function_table);
2384 		return FAILURE;
2385 	}
2386 	if (scope) {
2387 		scope->constructor = ctor;
2388 		scope->destructor = dtor;
2389 		scope->clone = clone;
2390 		scope->__call = __call;
2391 		scope->__callstatic = __callstatic;
2392 		scope->__tostring = __tostring;
2393 		scope->__get = __get;
2394 		scope->__set = __set;
2395 		scope->__unset = __unset;
2396 		scope->__isset = __isset;
2397 		scope->__debugInfo = __debugInfo;
2398 		scope->serialize_func = serialize_func;
2399 		scope->unserialize_func = unserialize_func;
2400 		if (ctor) {
2401 			ctor->common.fn_flags |= ZEND_ACC_CTOR;
2402 			if (ctor->common.fn_flags & ZEND_ACC_STATIC) {
2403 				zend_error(error_type, "Constructor %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(ctor->common.function_name));
2404 			}
2405 			ctor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2406 		}
2407 		if (dtor) {
2408 			dtor->common.fn_flags |= ZEND_ACC_DTOR;
2409 			if (dtor->common.fn_flags & ZEND_ACC_STATIC) {
2410 				zend_error(error_type, "Destructor %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(dtor->common.function_name));
2411 			}
2412 			dtor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2413 		}
2414 		if (clone) {
2415 			if (clone->common.fn_flags & ZEND_ACC_STATIC) {
2416 				zend_error(error_type, "%s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(clone->common.function_name));
2417 			}
2418 			clone->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2419 		}
2420 		if (__call) {
2421 			if (__call->common.fn_flags & ZEND_ACC_STATIC) {
2422 				zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__call->common.function_name));
2423 			}
2424 			__call->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2425 		}
2426 		if (__callstatic) {
2427 			if (!(__callstatic->common.fn_flags & ZEND_ACC_STATIC)) {
2428 				zend_error(error_type, "Method %s::%s() must be static", ZSTR_VAL(scope->name), ZSTR_VAL(__callstatic->common.function_name));
2429 			}
2430 			__callstatic->common.fn_flags |= ZEND_ACC_STATIC;
2431 		}
2432 		if (__tostring) {
2433 			if (__tostring->common.fn_flags & ZEND_ACC_STATIC) {
2434 				zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__tostring->common.function_name));
2435 			}
2436 			__tostring->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2437 		}
2438 		if (__get) {
2439 			if (__get->common.fn_flags & ZEND_ACC_STATIC) {
2440 				zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__get->common.function_name));
2441 			}
2442 			__get->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2443 		}
2444 		if (__set) {
2445 			if (__set->common.fn_flags & ZEND_ACC_STATIC) {
2446 				zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__set->common.function_name));
2447 			}
2448 			__set->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2449 		}
2450 		if (__unset) {
2451 			if (__unset->common.fn_flags & ZEND_ACC_STATIC) {
2452 				zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__unset->common.function_name));
2453 			}
2454 			__unset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2455 		}
2456 		if (__isset) {
2457 			if (__isset->common.fn_flags & ZEND_ACC_STATIC) {
2458 				zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__isset->common.function_name));
2459 			}
2460 			__isset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2461 		}
2462 		if (__debugInfo) {
2463 			if (__debugInfo->common.fn_flags & ZEND_ACC_STATIC) {
2464 				zend_error(error_type, "Method %s::%s() cannot be static", ZSTR_VAL(scope->name), ZSTR_VAL(__debugInfo->common.function_name));
2465 			}
2466 		}
2467 
2468 		if (ctor && (ctor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
2469 			zend_error_noreturn(E_CORE_ERROR, "Constructor %s::%s() cannot declare a return type", ZSTR_VAL(scope->name), ZSTR_VAL(ctor->common.function_name));
2470 		}
2471 
2472 		if (dtor && (dtor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
2473 			zend_error_noreturn(E_CORE_ERROR, "Destructor %s::%s() cannot declare a return type", ZSTR_VAL(scope->name), ZSTR_VAL(dtor->common.function_name));
2474 		}
2475 
2476 		if (clone && (clone->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
2477 			zend_error_noreturn(E_CORE_ERROR, "%s::%s() cannot declare a return type", ZSTR_VAL(scope->name), ZSTR_VAL(clone->common.function_name));
2478 		}
2479 		efree((char*)lc_class_name);
2480 	}
2481 	return SUCCESS;
2482 }
2483 /* }}} */
2484 
2485 /* count=-1 means erase all functions, otherwise,
2486  * erase the first count functions
2487  */
zend_unregister_functions(const zend_function_entry *functions, int count, HashTable *function_table)2488 ZEND_API void zend_unregister_functions(const zend_function_entry *functions, int count, HashTable *function_table) /* {{{ */
2489 {
2490 	const zend_function_entry *ptr = functions;
2491 	int i=0;
2492 	HashTable *target_function_table = function_table;
2493 	zend_string *lowercase_name;
2494 	size_t fname_len;
2495 
2496 	if (!target_function_table) {
2497 		target_function_table = CG(function_table);
2498 	}
2499 	while (ptr->fname) {
2500 		if (count!=-1 && i>=count) {
2501 			break;
2502 		}
2503 		fname_len = strlen(ptr->fname);
2504 		lowercase_name = zend_string_alloc(fname_len, 0);
2505 		zend_str_tolower_copy(ZSTR_VAL(lowercase_name), ptr->fname, fname_len);
2506 		zend_hash_del(target_function_table, lowercase_name);
2507 		zend_string_efree(lowercase_name);
2508 		ptr++;
2509 		i++;
2510 	}
2511 }
2512 /* }}} */
2513 
zend_startup_module(zend_module_entry *module)2514 ZEND_API int zend_startup_module(zend_module_entry *module) /* {{{ */
2515 {
2516 	if ((module = zend_register_internal_module(module)) != NULL && zend_startup_module_ex(module) == SUCCESS) {
2517 		return SUCCESS;
2518 	}
2519 	return FAILURE;
2520 }
2521 /* }}} */
2522 
zend_get_module_started(const char *module_name)2523 ZEND_API int zend_get_module_started(const char *module_name) /* {{{ */
2524 {
2525 	zend_module_entry *module;
2526 
2527 	module = zend_hash_str_find_ptr(&module_registry, module_name, strlen(module_name));
2528 	return (module && module->module_started) ? SUCCESS : FAILURE;
2529 }
2530 /* }}} */
2531 
clean_module_class(zval *el, void *arg)2532 static int clean_module_class(zval *el, void *arg) /* {{{ */
2533 {
2534 	zend_class_entry *ce = (zend_class_entry *)Z_PTR_P(el);
2535 	int module_number = *(int *)arg;
2536 	if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module->module_number == module_number) {
2537 		return ZEND_HASH_APPLY_REMOVE;
2538 	} else {
2539 		return ZEND_HASH_APPLY_KEEP;
2540 	}
2541 }
2542 /* }}} */
2543 
clean_module_classes(int module_number)2544 static void clean_module_classes(int module_number) /* {{{ */
2545 {
2546 	zend_hash_apply_with_argument(EG(class_table), clean_module_class, (void *) &module_number);
2547 }
2548 /* }}} */
2549 
module_destructor(zend_module_entry *module)2550 void module_destructor(zend_module_entry *module) /* {{{ */
2551 {
2552 
2553 	if (module->type == MODULE_TEMPORARY) {
2554 		zend_clean_module_rsrc_dtors(module->module_number);
2555 		clean_module_constants(module->module_number);
2556 		clean_module_classes(module->module_number);
2557 	}
2558 
2559 	if (module->module_started && module->module_shutdown_func) {
2560 #if 0
2561 		zend_printf("%s: Module shutdown\n", module->name);
2562 #endif
2563 		module->module_shutdown_func(module->type, module->module_number);
2564 	}
2565 
2566 	if (module->module_started
2567 	 && !module->module_shutdown_func
2568 	 && module->type == MODULE_TEMPORARY) {
2569 		zend_unregister_ini_entries(module->module_number);
2570 	}
2571 
2572 	/* Deinitilaise module globals */
2573 	if (module->globals_size) {
2574 #ifdef ZTS
2575 		if (*module->globals_id_ptr) {
2576 			ts_free_id(*module->globals_id_ptr);
2577 		}
2578 #else
2579 		if (module->globals_dtor) {
2580 			module->globals_dtor(module->globals_ptr);
2581 		}
2582 #endif
2583 	}
2584 
2585 	module->module_started=0;
2586 	if (module->type == MODULE_TEMPORARY && module->functions) {
2587 		zend_unregister_functions(module->functions, -1, NULL);
2588 	}
2589 
2590 #if HAVE_LIBDL
2591 	if (module->handle && !getenv("ZEND_DONT_UNLOAD_MODULES")) {
2592 		DL_UNLOAD(module->handle);
2593 	}
2594 #endif
2595 }
2596 /* }}} */
2597 
zend_activate_modules(void)2598 ZEND_API void zend_activate_modules(void) /* {{{ */
2599 {
2600 	zend_module_entry **p = module_request_startup_handlers;
2601 
2602 	while (*p) {
2603 		zend_module_entry *module = *p;
2604 
2605 		if (module->request_startup_func(module->type, module->module_number)==FAILURE) {
2606 			zend_error(E_WARNING, "request_startup() for %s module failed", module->name);
2607 			exit(1);
2608 		}
2609 		p++;
2610 	}
2611 }
2612 /* }}} */
2613 
zend_deactivate_modules(void)2614 ZEND_API void zend_deactivate_modules(void) /* {{{ */
2615 {
2616 	EG(current_execute_data) = NULL; /* we're no longer executing anything */
2617 
2618 	zend_try {
2619 		if (EG(full_tables_cleanup)) {
2620 			zend_module_entry *module;
2621 
2622 			ZEND_HASH_REVERSE_FOREACH_PTR(&module_registry, module) {
2623 				if (module->request_shutdown_func) {
2624 #if 0
2625 					zend_printf("%s: Request shutdown\n", module->name);
2626 #endif
2627 					module->request_shutdown_func(module->type, module->module_number);
2628 				}
2629 			} ZEND_HASH_FOREACH_END();
2630 		} else {
2631 			zend_module_entry **p = module_request_shutdown_handlers;
2632 
2633 			while (*p) {
2634 				zend_module_entry *module = *p;
2635 
2636 				module->request_shutdown_func(module->type, module->module_number);
2637 				p++;
2638 			}
2639 		}
2640 	} zend_end_try();
2641 }
2642 /* }}} */
2643 
zend_cleanup_internal_classes(void)2644 ZEND_API void zend_cleanup_internal_classes(void) /* {{{ */
2645 {
2646 	zend_class_entry **p = class_cleanup_handlers;
2647 
2648 	while (*p) {
2649 		zend_cleanup_internal_class_data(*p);
2650 		p++;
2651 	}
2652 }
2653 /* }}} */
2654 
zend_post_deactivate_modules(void)2655 ZEND_API void zend_post_deactivate_modules(void) /* {{{ */
2656 {
2657 	if (EG(full_tables_cleanup)) {
2658 		zend_module_entry *module;
2659 		zval *zv;
2660 		zend_string *key;
2661 
2662 		ZEND_HASH_FOREACH_PTR(&module_registry, module) {
2663 			if (module->post_deactivate_func) {
2664 				module->post_deactivate_func();
2665 			}
2666 		} ZEND_HASH_FOREACH_END();
2667 		ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(&module_registry, key, zv) {
2668 			module = Z_PTR_P(zv);
2669 			if (module->type != MODULE_TEMPORARY) {
2670 				break;
2671 			}
2672 			module_destructor(module);
2673 			free(module);
2674 			zend_string_release_ex(key, 0);
2675 		} ZEND_HASH_FOREACH_END_DEL();
2676 	} else {
2677 		zend_module_entry **p = module_post_deactivate_handlers;
2678 
2679 		while (*p) {
2680 			zend_module_entry *module = *p;
2681 
2682 			module->post_deactivate_func();
2683 			p++;
2684 		}
2685 	}
2686 }
2687 /* }}} */
2688 
2689 /* return the next free module number */
zend_next_free_module(void)2690 ZEND_API int zend_next_free_module(void) /* {{{ */
2691 {
2692 	return zend_hash_num_elements(&module_registry) + 1;
2693 }
2694 /* }}} */
2695 
do_register_internal_class(zend_class_entry *orig_class_entry, uint32_t ce_flags)2696 static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, uint32_t ce_flags) /* {{{ */
2697 {
2698 	zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
2699 	zend_string *lowercase_name;
2700 	*class_entry = *orig_class_entry;
2701 
2702 	class_entry->type = ZEND_INTERNAL_CLASS;
2703 	zend_initialize_class_data(class_entry, 0);
2704 	class_entry->ce_flags = ce_flags | ZEND_ACC_CONSTANTS_UPDATED | ZEND_ACC_LINKED | ZEND_ACC_RESOLVED_PARENT | ZEND_ACC_RESOLVED_INTERFACES;
2705 	class_entry->info.internal.module = EG(current_module);
2706 
2707 	if (class_entry->info.internal.builtin_functions) {
2708 		zend_register_functions(class_entry, class_entry->info.internal.builtin_functions, &class_entry->function_table, EG(current_module)->type);
2709 	}
2710 
2711 	lowercase_name = zend_string_tolower_ex(orig_class_entry->name, EG(current_module)->type == MODULE_PERSISTENT);
2712 	lowercase_name = zend_new_interned_string(lowercase_name);
2713 	zend_hash_update_ptr(CG(class_table), lowercase_name, class_entry);
2714 	zend_string_release_ex(lowercase_name, 1);
2715 	return class_entry;
2716 }
2717 /* }}} */
2718 
2719 /* If parent_ce is not NULL then it inherits from parent_ce
2720  * If parent_ce is NULL and parent_name isn't then it looks for the parent and inherits from it
2721  * If both parent_ce and parent_name are NULL it does a regular class registration
2722  * If parent_name is specified but not found NULL is returned
2723  */
zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce)2724 ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce) /* {{{ */
2725 {
2726 	zend_class_entry *register_class;
2727 
2728 	register_class = zend_register_internal_class(class_entry);
2729 
2730 	if (parent_ce) {
2731 		zend_do_inheritance(register_class, parent_ce);
2732 		zend_build_properties_info_table(register_class);
2733 	}
2734 	return register_class;
2735 }
2736 /* }}} */
2737 
zend_class_implements(zend_class_entry *class_entry, int num_interfaces, ...)2738 ZEND_API void zend_class_implements(zend_class_entry *class_entry, int num_interfaces, ...) /* {{{ */
2739 {
2740 	zend_class_entry *interface_entry;
2741 	va_list interface_list;
2742 	va_start(interface_list, num_interfaces);
2743 
2744 	while (num_interfaces--) {
2745 		interface_entry = va_arg(interface_list, zend_class_entry *);
2746 		zend_do_implement_interface(class_entry, interface_entry);
2747 	}
2748 
2749 	va_end(interface_list);
2750 }
2751 /* }}} */
2752 
2753 /* A class that contains at least one abstract method automatically becomes an abstract class.
2754  */
zend_register_internal_class(zend_class_entry *orig_class_entry)2755 ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry) /* {{{ */
2756 {
2757 	return do_register_internal_class(orig_class_entry, 0);
2758 }
2759 /* }}} */
2760 
zend_register_internal_interface(zend_class_entry *orig_class_entry)2761 ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry) /* {{{ */
2762 {
2763 	return do_register_internal_class(orig_class_entry, ZEND_ACC_INTERFACE);
2764 }
2765 /* }}} */
2766 
zend_register_class_alias_ex(const char *name, size_t name_len, zend_class_entry *ce, int persistent)2767 ZEND_API int zend_register_class_alias_ex(const char *name, size_t name_len, zend_class_entry *ce, int persistent) /* {{{ */
2768 {
2769 	zend_string *lcname;
2770 	zval zv, *ret;
2771 
2772 	/* TODO: Move this out of here in 7.4. */
2773 	if (persistent && EG(current_module) && EG(current_module)->type == MODULE_TEMPORARY) {
2774 		persistent = 0;
2775 	}
2776 
2777 	if (name[0] == '\\') {
2778 		lcname = zend_string_alloc(name_len-1, persistent);
2779 		zend_str_tolower_copy(ZSTR_VAL(lcname), name+1, name_len-1);
2780 	} else {
2781 		lcname = zend_string_alloc(name_len, persistent);
2782 		zend_str_tolower_copy(ZSTR_VAL(lcname), name, name_len);
2783 	}
2784 
2785 	zend_assert_valid_class_name(lcname);
2786 
2787 	lcname = zend_new_interned_string(lcname);
2788 
2789 	ZVAL_ALIAS_PTR(&zv, ce);
2790 	ret = zend_hash_add(CG(class_table), lcname, &zv);
2791 	zend_string_release_ex(lcname, 0);
2792 	if (ret) {
2793 		if (!(ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
2794 			ce->refcount++;
2795 		}
2796 		return SUCCESS;
2797 	}
2798 	return FAILURE;
2799 }
2800 /* }}} */
2801 
zend_set_hash_symbol(zval *symbol, const char *name, int name_length, zend_bool is_ref, int num_symbol_tables, ...)2802 ZEND_API int zend_set_hash_symbol(zval *symbol, const char *name, int name_length, zend_bool is_ref, int num_symbol_tables, ...) /* {{{ */
2803 {
2804 	HashTable *symbol_table;
2805 	va_list symbol_table_list;
2806 
2807 	if (num_symbol_tables <= 0) return FAILURE;
2808 
2809 	if (is_ref) {
2810 		ZVAL_MAKE_REF(symbol);
2811 	}
2812 
2813 	va_start(symbol_table_list, num_symbol_tables);
2814 	while (num_symbol_tables-- > 0) {
2815 		symbol_table = va_arg(symbol_table_list, HashTable *);
2816 		zend_hash_str_update(symbol_table, name, name_length, symbol);
2817 		Z_TRY_ADDREF_P(symbol);
2818 	}
2819 	va_end(symbol_table_list);
2820 	return SUCCESS;
2821 }
2822 /* }}} */
2823 
2824 /* Disabled functions support */
2825 
2826 /* {{{ proto void display_disabled_function(void)
2827 Dummy function which displays an error when a disabled function is called. */
ZEND_FUNCTIONnull2828 ZEND_API ZEND_COLD ZEND_FUNCTION(display_disabled_function)
2829 {
2830 	zend_error(E_WARNING, "%s() has been disabled for security reasons", get_active_function_name());
2831 }
2832 /* }}} */
2833 
zend_disable_function(char *function_name, size_t function_name_length)2834 ZEND_API int zend_disable_function(char *function_name, size_t function_name_length) /* {{{ */
2835 {
2836 	zend_internal_function *func;
2837 	if ((func = zend_hash_str_find_ptr(CG(function_table), function_name, function_name_length))) {
2838 		zend_free_internal_arg_info(func);
2839 	    func->fn_flags &= ~(ZEND_ACC_VARIADIC | ZEND_ACC_HAS_TYPE_HINTS | ZEND_ACC_HAS_RETURN_TYPE);
2840 		func->num_args = 0;
2841 		func->arg_info = NULL;
2842 		func->handler = ZEND_FN(display_disabled_function);
2843 		return SUCCESS;
2844 	}
2845 	return FAILURE;
2846 }
2847 /* }}} */
2848 
2849 #ifdef ZEND_WIN32
2850 #pragma optimize("", off)
2851 #endif
display_disabled_class(zend_class_entry *class_type)2852 static ZEND_COLD zend_object *display_disabled_class(zend_class_entry *class_type) /* {{{ */
2853 {
2854 	zend_object *intern;
2855 
2856 	intern = zend_objects_new(class_type);
2857 
2858 	/* Initialize default properties */
2859 	if (EXPECTED(class_type->default_properties_count != 0)) {
2860 		zval *p = intern->properties_table;
2861 		zval *end = p + class_type->default_properties_count;
2862 		do {
2863 			ZVAL_UNDEF(p);
2864 			p++;
2865 		} while (p != end);
2866 	}
2867 
2868 	zend_error(E_WARNING, "%s() has been disabled for security reasons", ZSTR_VAL(class_type->name));
2869 	return intern;
2870 }
2871 #ifdef ZEND_WIN32
2872 #pragma optimize("", on)
2873 #endif
2874 /* }}} */
2875 
2876 static const zend_function_entry disabled_class_new[] = {
2877 	ZEND_FE_END
2878 };
2879 
zend_disable_class(char *class_name, size_t class_name_length)2880 ZEND_API int zend_disable_class(char *class_name, size_t class_name_length) /* {{{ */
2881 {
2882 	zend_class_entry *disabled_class;
2883 	zend_string *key;
2884 	zend_function *fn;
2885 
2886 	key = zend_string_alloc(class_name_length, 0);
2887 	zend_str_tolower_copy(ZSTR_VAL(key), class_name, class_name_length);
2888 	disabled_class = zend_hash_find_ptr(CG(class_table), key);
2889 	zend_string_release_ex(key, 0);
2890 	if (!disabled_class) {
2891 		return FAILURE;
2892 	}
2893 
2894 	INIT_CLASS_ENTRY_INIT_METHODS((*disabled_class), disabled_class_new);
2895 	disabled_class->create_object = display_disabled_class;
2896 
2897 	ZEND_HASH_FOREACH_PTR(&disabled_class->function_table, fn) {
2898 		if ((fn->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) &&
2899 			fn->common.scope == disabled_class) {
2900 			zend_free_internal_arg_info(&fn->internal_function);
2901 		}
2902 	} ZEND_HASH_FOREACH_END();
2903 	zend_hash_clean(&disabled_class->function_table);
2904 	return SUCCESS;
2905 }
2906 /* }}} */
2907 
zend_is_callable_check_class(zend_string *name, zend_class_entry *scope, zend_fcall_info_cache *fcc, int *strict_class, char **error)2908 static int zend_is_callable_check_class(zend_string *name, zend_class_entry *scope, zend_fcall_info_cache *fcc, int *strict_class, char **error) /* {{{ */
2909 {
2910 	int ret = 0;
2911 	zend_class_entry *ce;
2912 	size_t name_len = ZSTR_LEN(name);
2913 	zend_string *lcname;
2914 	ALLOCA_FLAG(use_heap);
2915 
2916 	ZSTR_ALLOCA_ALLOC(lcname, name_len, use_heap);
2917 	zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(name),