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