xref: /PHP-8.2/Zend/zend_API.c (revision d41e97ae)
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 #include "zend_enum.h"
34 #include "zend_observer.h"
35 
36 #include <stdarg.h>
37 
38 /* these variables are true statics/globals, and have to be mutex'ed on every access */
39 ZEND_API HashTable module_registry;
40 
41 static zend_module_entry **module_request_startup_handlers;
42 static zend_module_entry **module_request_shutdown_handlers;
43 static zend_module_entry **module_post_deactivate_handlers;
44 static zend_module_entry **modules_dl_loaded;
45 
46 static zend_class_entry  **class_cleanup_handlers;
47 
zend_get_parameters_array_ex(uint32_t param_count,zval * argument_array)48 ZEND_API zend_result zend_get_parameters_array_ex(uint32_t param_count, zval *argument_array) /* {{{ */
49 {
50 	zval *param_ptr;
51 	uint32_t arg_count;
52 
53 	param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1);
54 	arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
55 
56 	if (param_count>arg_count) {
57 		return FAILURE;
58 	}
59 
60 	while (param_count-->0) {
61 		ZVAL_COPY_VALUE(argument_array, param_ptr);
62 		argument_array++;
63 		param_ptr++;
64 	}
65 
66 	return SUCCESS;
67 }
68 /* }}} */
69 
zend_copy_parameters_array(uint32_t param_count,zval * argument_array)70 ZEND_API zend_result zend_copy_parameters_array(uint32_t param_count, zval *argument_array) /* {{{ */
71 {
72 	zval *param_ptr;
73 	uint32_t arg_count;
74 
75 	param_ptr = ZEND_CALL_ARG(EG(current_execute_data), 1);
76 	arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
77 
78 	if (param_count>arg_count) {
79 		return FAILURE;
80 	}
81 
82 	while (param_count-->0) {
83 		Z_TRY_ADDREF_P(param_ptr);
84 		zend_hash_next_index_insert_new(Z_ARRVAL_P(argument_array), param_ptr);
85 		param_ptr++;
86 	}
87 
88 	return SUCCESS;
89 }
90 /* }}} */
91 
zend_wrong_param_count(void)92 ZEND_API ZEND_COLD void zend_wrong_param_count(void) /* {{{ */
93 {
94 	const char *space;
95 	const char *class_name = get_active_class_name(&space);
96 
97 	zend_argument_count_error("Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name());
98 }
99 /* }}} */
100 
zend_wrong_property_read(zval * object,zval * property)101 ZEND_API ZEND_COLD void zend_wrong_property_read(zval *object, zval *property)
102 {
103 	zend_string *tmp_property_name;
104 	zend_string *property_name = zval_get_tmp_string(property, &tmp_property_name);
105 	zend_error(E_WARNING, "Attempt to read property \"%s\" on %s", ZSTR_VAL(property_name), zend_zval_type_name(object));
106 	zend_tmp_string_release(tmp_property_name);
107 }
108 
109 /* Argument parsing API -- andrei */
zend_get_type_by_const(int type)110 ZEND_API const char *zend_get_type_by_const(int type) /* {{{ */
111 {
112 	switch(type) {
113 		case IS_FALSE:
114 		case IS_TRUE:
115 		case _IS_BOOL:
116 			return "bool";
117 		case IS_LONG:
118 			return "int";
119 		case IS_DOUBLE:
120 			return "float";
121 		case IS_STRING:
122 			return "string";
123 		case IS_OBJECT:
124 			return "object";
125 		case IS_RESOURCE:
126 			return "resource";
127 		case IS_NULL:
128 			return "null";
129 		case IS_CALLABLE:
130 			return "callable";
131 		case IS_ITERABLE:
132 			return "iterable";
133 		case IS_ARRAY:
134 			return "array";
135 		case IS_VOID:
136 			return "void";
137 		case IS_MIXED:
138 			return "mixed";
139 		case _IS_NUMBER:
140 			return "number";
141 		EMPTY_SWITCH_DEFAULT_CASE()
142 	}
143 }
144 /* }}} */
145 
zend_zval_type_name(const zval * arg)146 ZEND_API const char *zend_zval_type_name(const zval *arg) /* {{{ */
147 {
148 	ZVAL_DEREF(arg);
149 
150 	if (Z_ISUNDEF_P(arg)) {
151 		return "null";
152 	}
153 
154 	if (Z_TYPE_P(arg) == IS_OBJECT) {
155 		return ZSTR_VAL(Z_OBJCE_P(arg)->name);
156 	}
157 
158 	return zend_get_type_by_const(Z_TYPE_P(arg));
159 }
160 /* }}} */
161 
162 /* This API exists *only* for use in gettype().
163  * For anything else, you likely want zend_zval_type_name(). */
zend_zval_get_legacy_type(const zval * arg)164 ZEND_API zend_string *zend_zval_get_legacy_type(const zval *arg) /* {{{ */
165 {
166 	switch (Z_TYPE_P(arg)) {
167 		case IS_NULL:
168 			return ZSTR_KNOWN(ZEND_STR_NULL);
169 		case IS_FALSE:
170 		case IS_TRUE:
171 			return ZSTR_KNOWN(ZEND_STR_BOOLEAN);
172 		case IS_LONG:
173 			return ZSTR_KNOWN(ZEND_STR_INTEGER);
174 		case IS_DOUBLE:
175 			return ZSTR_KNOWN(ZEND_STR_DOUBLE);
176 		case IS_STRING:
177 			return ZSTR_KNOWN(ZEND_STR_STRING);
178 		case IS_ARRAY:
179 			return ZSTR_KNOWN(ZEND_STR_ARRAY);
180 		case IS_OBJECT:
181 			return ZSTR_KNOWN(ZEND_STR_OBJECT);
182 		case IS_RESOURCE:
183 			if (zend_rsrc_list_get_rsrc_type(Z_RES_P(arg))) {
184 				return ZSTR_KNOWN(ZEND_STR_RESOURCE);
185 			} else {
186 				return ZSTR_KNOWN(ZEND_STR_CLOSED_RESOURCE);
187 			}
188 		default:
189 			return NULL;
190 	}
191 }
192 /* }}} */
193 
zend_wrong_parameters_none_error(void)194 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_none_error(void) /* {{{ */
195 {
196 	int num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
197 	zend_string *func_name = get_active_function_or_method_name();
198 
199 	zend_argument_count_error("%s() expects exactly 0 arguments, %d given", ZSTR_VAL(func_name), num_args);
200 
201 	zend_string_release(func_name);
202 }
203 /* }}} */
204 
zend_wrong_parameters_count_error(uint32_t min_num_args,uint32_t max_num_args)205 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameters_count_error(uint32_t min_num_args, uint32_t max_num_args) /* {{{ */
206 {
207 	uint32_t num_args = ZEND_CALL_NUM_ARGS(EG(current_execute_data));
208 	zend_string *func_name = get_active_function_or_method_name();
209 
210 	zend_argument_count_error(
211 		"%s() expects %s %d argument%s, %d given",
212 		ZSTR_VAL(func_name),
213 		min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
214 		num_args < min_num_args ? min_num_args : max_num_args,
215 		(num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
216 		num_args
217 	);
218 
219 	zend_string_release(func_name);
220 }
221 /* }}} */
222 
zend_wrong_parameter_error(int error_code,uint32_t num,char * name,zend_expected_type expected_type,zval * arg)223 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_error(int error_code, uint32_t num, char *name, zend_expected_type expected_type, zval *arg) /* {{{ */
224 {
225 	switch (error_code) {
226 		case ZPP_ERROR_WRONG_CALLBACK:
227 			zend_wrong_callback_error(num, name);
228 			break;
229 		case ZPP_ERROR_WRONG_CALLBACK_OR_NULL:
230 			zend_wrong_callback_or_null_error(num, name);
231 			break;
232 		case ZPP_ERROR_WRONG_CLASS:
233 			zend_wrong_parameter_class_error(num, name, arg);
234 			break;
235 		case ZPP_ERROR_WRONG_CLASS_OR_NULL:
236 			zend_wrong_parameter_class_or_null_error(num, name, arg);
237 			break;
238 		case ZPP_ERROR_WRONG_CLASS_OR_STRING:
239 			zend_wrong_parameter_class_or_string_error(num, name, arg);
240 			break;
241 		case ZPP_ERROR_WRONG_CLASS_OR_STRING_OR_NULL:
242 			zend_wrong_parameter_class_or_string_or_null_error(num, name, arg);
243 			break;
244 		case ZPP_ERROR_WRONG_CLASS_OR_LONG:
245 			zend_wrong_parameter_class_or_long_error(num, name, arg);
246 			break;
247 		case ZPP_ERROR_WRONG_CLASS_OR_LONG_OR_NULL:
248 			zend_wrong_parameter_class_or_long_or_null_error(num, name, arg);
249 			break;
250 		case ZPP_ERROR_WRONG_ARG:
251 			zend_wrong_parameter_type_error(num, expected_type, arg);
252 			break;
253 		case ZPP_ERROR_UNEXPECTED_EXTRA_NAMED:
254 			zend_unexpected_extra_named_error();
255 			break;
256 		case ZPP_ERROR_FAILURE:
257 			ZEND_ASSERT(EG(exception) && "Should have produced an error already");
258 			break;
259 		EMPTY_SWITCH_DEFAULT_CASE()
260 	}
261 }
262 /* }}} */
263 
zend_wrong_parameter_type_error(uint32_t num,zend_expected_type expected_type,zval * arg)264 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(uint32_t num, zend_expected_type expected_type, zval *arg) /* {{{ */
265 {
266 	static const char * const expected_error[] = {
267 		Z_EXPECTED_TYPES(Z_EXPECTED_TYPE_STR)
268 		NULL
269 	};
270 
271 	if (EG(exception)) {
272 		return;
273 	}
274 
275 	if ((expected_type == Z_EXPECTED_PATH || expected_type == Z_EXPECTED_PATH_OR_NULL)
276 			&& Z_TYPE_P(arg) == IS_STRING) {
277 		zend_argument_value_error(num, "must not contain any null bytes");
278 		return;
279 	}
280 
281 	zend_argument_type_error(num, "must be %s, %s given", expected_error[expected_type], zend_zval_type_name(arg));
282 }
283 /* }}} */
284 
zend_wrong_parameter_class_error(uint32_t num,const char * name,zval * arg)285 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(uint32_t num, const char *name, zval *arg) /* {{{ */
286 {
287 	if (EG(exception)) {
288 		return;
289 	}
290 
291 	zend_argument_type_error(num, "must be of type %s, %s given", name, zend_zval_type_name(arg));
292 }
293 /* }}} */
294 
zend_wrong_parameter_class_or_null_error(uint32_t num,const char * name,zval * arg)295 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_null_error(uint32_t num, const char *name, zval *arg) /* {{{ */
296 {
297 	if (EG(exception)) {
298 		return;
299 	}
300 
301 	zend_argument_type_error(num, "must be of type ?%s, %s given", name, zend_zval_type_name(arg));
302 }
303 /* }}} */
304 
zend_wrong_parameter_class_or_long_error(uint32_t num,const char * name,zval * arg)305 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_error(uint32_t num, const char *name, zval *arg) /* {{{ */
306 {
307 	if (EG(exception)) {
308 		return;
309 	}
310 
311 	zend_argument_type_error(num, "must be of type %s|int, %s given", name, zend_zval_type_name(arg));
312 }
313 /* }}} */
314 
zend_wrong_parameter_class_or_long_or_null_error(uint32_t num,const char * name,zval * arg)315 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_or_null_error(uint32_t num, const char *name, zval *arg) /* {{{ */
316 {
317 	if (EG(exception)) {
318 		return;
319 	}
320 
321 	zend_argument_type_error(num, "must be of type %s|int|null, %s given", name, zend_zval_type_name(arg));
322 }
323 /* }}} */
324 
zend_wrong_parameter_class_or_string_error(uint32_t num,const char * name,zval * arg)325 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_error(uint32_t num, const char *name, zval *arg) /* {{{ */
326 {
327 	if (EG(exception)) {
328 		return;
329 	}
330 
331 	zend_argument_type_error(num, "must be of type %s|string, %s given", name, zend_zval_type_name(arg));
332 }
333 /* }}} */
334 
zend_wrong_parameter_class_or_string_or_null_error(uint32_t num,const char * name,zval * arg)335 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_or_null_error(uint32_t num, const char *name, zval *arg) /* {{{ */
336 {
337 	if (EG(exception)) {
338 		return;
339 	}
340 
341 	zend_argument_type_error(num, "must be of type %s|string|null, %s given", name, zend_zval_type_name(arg));
342 }
343 /* }}} */
344 
zend_wrong_callback_error(uint32_t num,char * error)345 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(uint32_t num, char *error) /* {{{ */
346 {
347 	if (!EG(exception)) {
348 		zend_argument_type_error(num, "must be a valid callback, %s", error);
349 	}
350 	efree(error);
351 }
352 /* }}} */
353 
zend_wrong_callback_or_null_error(uint32_t num,char * error)354 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_or_null_error(uint32_t num, char *error) /* {{{ */
355 {
356 	if (!EG(exception)) {
357 		zend_argument_type_error(num, "must be a valid callback or null, %s", error);
358 	}
359 	efree(error);
360 }
361 /* }}} */
362 
zend_unexpected_extra_named_error(void)363 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_unexpected_extra_named_error(void)
364 {
365 	const char *space;
366 	const char *class_name = get_active_class_name(&space);
367 	zend_argument_count_error("%s%s%s() does not accept unknown named parameters",
368 		class_name, space, get_active_function_name());
369 }
370 
zend_argument_error_variadic(zend_class_entry * error_ce,uint32_t arg_num,const char * format,va_list va)371 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) /* {{{ */
372 {
373 	zend_string *func_name;
374 	const char *arg_name;
375 	char *message = NULL;
376 	if (EG(exception)) {
377 		return;
378 	}
379 
380 	func_name = get_active_function_or_method_name();
381 	arg_name = get_active_function_arg_name(arg_num);
382 
383 	zend_vspprintf(&message, 0, format, va);
384 	zend_throw_error(error_ce, "%s(): Argument #%d%s%s%s %s",
385 		ZSTR_VAL(func_name), arg_num,
386 		arg_name ? " ($" : "", arg_name ? arg_name : "", arg_name ? ")" : "", message
387 	);
388 	efree(message);
389 	zend_string_release(func_name);
390 }
391 /* }}} */
392 
zend_argument_error(zend_class_entry * error_ce,uint32_t arg_num,const char * format,...)393 ZEND_API ZEND_COLD void zend_argument_error(zend_class_entry *error_ce, uint32_t arg_num, const char *format, ...) /* {{{ */
394 {
395 	va_list va;
396 
397 	va_start(va, format);
398 	zend_argument_error_variadic(error_ce, arg_num, format, va);
399 	va_end(va);
400 }
401 /* }}} */
402 
zend_argument_type_error(uint32_t arg_num,const char * format,...)403 ZEND_API ZEND_COLD void zend_argument_type_error(uint32_t arg_num, const char *format, ...) /* {{{ */
404 {
405 	va_list va;
406 
407 	va_start(va, format);
408 	zend_argument_error_variadic(zend_ce_type_error, arg_num, format, va);
409 	va_end(va);
410 }
411 /* }}} */
412 
zend_argument_value_error(uint32_t arg_num,const char * format,...)413 ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *format, ...) /* {{{ */
414 {
415 	va_list va;
416 
417 	va_start(va, format);
418 	zend_argument_error_variadic(zend_ce_value_error, arg_num, format, va);
419 	va_end(va);
420 }
421 /* }}} */
422 
zend_parse_arg_class(zval * arg,zend_class_entry ** pce,uint32_t num,bool check_null)423 ZEND_API bool ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **pce, uint32_t num, bool check_null) /* {{{ */
424 {
425 	zend_class_entry *ce_base = *pce;
426 
427 	if (check_null && Z_TYPE_P(arg) == IS_NULL) {
428 		*pce = NULL;
429 		return 1;
430 	}
431 	if (!try_convert_to_string(arg)) {
432 		*pce = NULL;
433 		return 0;
434 	}
435 
436 	*pce = zend_lookup_class(Z_STR_P(arg));
437 	if (ce_base) {
438 		if ((!*pce || !instanceof_function(*pce, ce_base))) {
439 			zend_argument_type_error(num, "must be a class name derived from %s, %s given", ZSTR_VAL(ce_base->name), Z_STRVAL_P(arg));
440 			*pce = NULL;
441 			return 0;
442 		}
443 	}
444 	if (!*pce) {
445 		zend_argument_type_error(num, "must be a valid class name, %s given", Z_STRVAL_P(arg));
446 		return 0;
447 	}
448 	return 1;
449 }
450 /* }}} */
451 
zend_null_arg_deprecated(const char * fallback_type,uint32_t arg_num)452 static ZEND_COLD bool zend_null_arg_deprecated(const char *fallback_type, uint32_t arg_num) {
453 	zend_function *func = EG(current_execute_data)->func;
454 	ZEND_ASSERT(arg_num > 0);
455 	uint32_t arg_offset = arg_num - 1;
456 	if (arg_offset >= func->common.num_args) {
457 		ZEND_ASSERT(func->common.fn_flags & ZEND_ACC_VARIADIC);
458 		arg_offset = func->common.num_args;
459 	}
460 
461 	zend_arg_info *arg_info = &func->common.arg_info[arg_offset];
462 	zend_string *func_name = get_active_function_or_method_name();
463 	const char *arg_name = get_active_function_arg_name(arg_num);
464 
465 	/* If no type is specified in arginfo, use the specified fallback_type determined through
466 	 * zend_parse_parameters instead. */
467 	zend_string *type_str = zend_type_to_string(arg_info->type);
468 	const char *type = type_str ? ZSTR_VAL(type_str) : fallback_type;
469 	zend_error(E_DEPRECATED,
470 		"%s(): Passing null to parameter #%" PRIu32 "%s%s%s of type %s is deprecated",
471 		ZSTR_VAL(func_name), arg_num,
472 		arg_name ? " ($" : "", arg_name ? arg_name : "", arg_name ? ")" : "",
473 		type);
474 	zend_string_release(func_name);
475 	if (type_str) {
476 		zend_string_release(type_str);
477 	}
478 	return !EG(exception);
479 }
480 
zend_parse_arg_bool_weak(zval * arg,bool * dest,uint32_t arg_num)481 ZEND_API bool ZEND_FASTCALL zend_parse_arg_bool_weak(zval *arg, bool *dest, uint32_t arg_num) /* {{{ */
482 {
483 	if (EXPECTED(Z_TYPE_P(arg) <= IS_STRING)) {
484 		if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("bool", arg_num)) {
485 			return 0;
486 		}
487 		*dest = zend_is_true(arg);
488 	} else {
489 		return 0;
490 	}
491 	return 1;
492 }
493 /* }}} */
494 
zend_parse_arg_bool_slow(zval * arg,bool * dest,uint32_t arg_num)495 ZEND_API bool ZEND_FASTCALL zend_parse_arg_bool_slow(zval *arg, bool *dest, uint32_t arg_num) /* {{{ */
496 {
497 	if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
498 		return 0;
499 	}
500 	return zend_parse_arg_bool_weak(arg, dest, arg_num);
501 }
502 /* }}} */
503 
zend_parse_arg_long_weak(zval * arg,zend_long * dest,uint32_t arg_num)504 ZEND_API bool ZEND_FASTCALL zend_parse_arg_long_weak(zval *arg, zend_long *dest, uint32_t arg_num) /* {{{ */
505 {
506 	if (EXPECTED(Z_TYPE_P(arg) == IS_DOUBLE)) {
507 		if (UNEXPECTED(zend_isnan(Z_DVAL_P(arg)))) {
508 			return 0;
509 		}
510 		if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(Z_DVAL_P(arg)))) {
511 			return 0;
512 		} else {
513 			zend_long lval = zend_dval_to_lval(Z_DVAL_P(arg));
514 			if (UNEXPECTED(!zend_is_long_compatible(Z_DVAL_P(arg), lval))) {
515 				/* Check arg_num is not (uint32_t)-1, as otherwise its called by
516 				 * zend_verify_weak_scalar_type_hint_no_sideeffect() */
517 				if (arg_num != (uint32_t)-1) {
518 					zend_incompatible_double_to_long_error(Z_DVAL_P(arg));
519 				}
520 				if (UNEXPECTED(EG(exception))) {
521 					return 0;
522 				}
523 			}
524 			*dest = lval;
525 		}
526 	} else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
527 		double d;
528 		zend_uchar type;
529 
530 		if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), dest, &d)) != IS_LONG)) {
531 			if (EXPECTED(type != 0)) {
532 				zend_long lval;
533 				if (UNEXPECTED(zend_isnan(d))) {
534 					return 0;
535 				}
536 				if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(d))) {
537 					return 0;
538 				}
539 
540 				lval = zend_dval_to_lval(d);
541 				/* This only checks for a fractional part as if doesn't fit it already throws a TypeError */
542 				if (UNEXPECTED(!zend_is_long_compatible(d, lval))) {
543 					/* Check arg_num is not (uint32_t)-1, as otherwise its called by
544 					 * zend_verify_weak_scalar_type_hint_no_sideeffect() */
545 					if (arg_num != (uint32_t)-1) {
546 						zend_incompatible_string_to_long_error(Z_STR_P(arg));
547 					}
548 					if (UNEXPECTED(EG(exception))) {
549 						return 0;
550 					}
551 				}
552 				*dest = lval;
553 			} else {
554 				return 0;
555 			}
556 		}
557 		if (UNEXPECTED(EG(exception))) {
558 			return 0;
559 		}
560 	} else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
561 		if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("int", arg_num)) {
562 			return 0;
563 		}
564 		*dest = 0;
565 	} else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
566 		*dest = 1;
567 	} else {
568 		return 0;
569 	}
570 	return 1;
571 }
572 /* }}} */
573 
zend_parse_arg_long_slow(zval * arg,zend_long * dest,uint32_t arg_num)574 ZEND_API bool ZEND_FASTCALL zend_parse_arg_long_slow(zval *arg, zend_long *dest, uint32_t arg_num) /* {{{ */
575 {
576 	if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
577 		return 0;
578 	}
579 	return zend_parse_arg_long_weak(arg, dest, arg_num);
580 }
581 /* }}} */
582 
zend_parse_arg_double_weak(zval * arg,double * dest,uint32_t arg_num)583 ZEND_API bool ZEND_FASTCALL zend_parse_arg_double_weak(zval *arg, double *dest, uint32_t arg_num) /* {{{ */
584 {
585 	if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
586 		*dest = (double)Z_LVAL_P(arg);
587 	} else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
588 		zend_long l;
589 		zend_uchar type;
590 
591 		if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), &l, dest)) != IS_DOUBLE)) {
592 			if (EXPECTED(type != 0)) {
593 				*dest = (double)(l);
594 			} else {
595 				return 0;
596 			}
597 		}
598 		if (UNEXPECTED(EG(exception))) {
599 			return 0;
600 		}
601 	} else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
602 		if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("float", arg_num)) {
603 			return 0;
604 		}
605 		*dest = 0.0;
606 	} else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
607 		*dest = 1.0;
608 	} else {
609 		return 0;
610 	}
611 	return 1;
612 }
613 /* }}} */
614 
zend_parse_arg_double_slow(zval * arg,double * dest,uint32_t arg_num)615 ZEND_API bool ZEND_FASTCALL zend_parse_arg_double_slow(zval *arg, double *dest, uint32_t arg_num) /* {{{ */
616 {
617 	if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
618 		/* SSTH Exception: IS_LONG may be accepted instead as IS_DOUBLE */
619 		*dest = (double)Z_LVAL_P(arg);
620 	} else if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
621 		return 0;
622 	}
623 	return zend_parse_arg_double_weak(arg, dest, arg_num);
624 }
625 /* }}} */
626 
zend_parse_arg_number_slow(zval * arg,zval ** dest,uint32_t arg_num)627 ZEND_API bool ZEND_FASTCALL zend_parse_arg_number_slow(zval *arg, zval **dest, uint32_t arg_num) /* {{{ */
628 {
629 	if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
630 		return 0;
631 	}
632 	if (Z_TYPE_P(arg) == IS_STRING) {
633 		zend_string *str = Z_STR_P(arg);
634 		zend_long lval;
635 		double dval;
636 		zend_uchar type = is_numeric_str_function(str, &lval, &dval);
637 		if (type == IS_LONG) {
638 			ZVAL_LONG(arg, lval);
639 		} else if (type == IS_DOUBLE) {
640 			ZVAL_DOUBLE(arg, dval);
641 		} else {
642 			return 0;
643 		}
644 		zend_string_release(str);
645 	} else if (Z_TYPE_P(arg) < IS_TRUE) {
646 		if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("int|float", arg_num)) {
647 			return 0;
648 		}
649 		ZVAL_LONG(arg, 0);
650 	} else if (Z_TYPE_P(arg) == IS_TRUE) {
651 		ZVAL_LONG(arg, 1);
652 	} else {
653 		return 0;
654 	}
655 	*dest = arg;
656 	return 1;
657 }
658 /* }}} */
659 
zend_parse_arg_str_weak(zval * arg,zend_string ** dest,uint32_t arg_num)660 ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest, uint32_t arg_num) /* {{{ */
661 {
662 	if (EXPECTED(Z_TYPE_P(arg) < IS_STRING)) {
663 		if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("string", arg_num)) {
664 			return 0;
665 		}
666 		convert_to_string(arg);
667 		*dest = Z_STR_P(arg);
668 	} else if (UNEXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
669 		zend_object *zobj = Z_OBJ_P(arg);
670 		zval obj;
671 		if (zobj->handlers->cast_object(zobj, &obj, IS_STRING) == SUCCESS) {
672 			OBJ_RELEASE(zobj);
673 			ZVAL_COPY_VALUE(arg, &obj);
674 			*dest = Z_STR_P(arg);
675 			return 1;
676 		}
677 		return 0;
678 	} else {
679 		return 0;
680 	}
681 	return 1;
682 }
683 /* }}} */
684 
zend_parse_arg_str_slow(zval * arg,zend_string ** dest,uint32_t arg_num)685 ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, zend_string **dest, uint32_t arg_num) /* {{{ */
686 {
687 	if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
688 		return 0;
689 	}
690 	return zend_parse_arg_str_weak(arg, dest, arg_num);
691 }
692 /* }}} */
693 
zend_parse_arg_str_or_long_slow(zval * arg,zend_string ** dest_str,zend_long * dest_long,uint32_t arg_num)694 ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_or_long_slow(zval *arg, zend_string **dest_str, zend_long *dest_long, uint32_t arg_num) /* {{{ */
695 {
696 	if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) {
697 		return 0;
698 	}
699 	if (zend_parse_arg_long_weak(arg, dest_long, arg_num)) {
700 		*dest_str = NULL;
701 		return 1;
702 	} else if (zend_parse_arg_str_weak(arg, dest_str, arg_num)) {
703 		*dest_long = 0;
704 		return 1;
705 	} else {
706 		return 0;
707 	}
708 }
709 /* }}} */
710 
zend_parse_arg_impl(zval * arg,va_list * va,const char ** spec,char ** error,uint32_t arg_num)711 static const char *zend_parse_arg_impl(zval *arg, va_list *va, const char **spec, char **error, uint32_t arg_num) /* {{{ */
712 {
713 	const char *spec_walk = *spec;
714 	char c = *spec_walk++;
715 	bool check_null = 0;
716 	bool separate = 0;
717 	zval *real_arg = arg;
718 
719 	/* scan through modifiers */
720 	ZVAL_DEREF(arg);
721 	while (1) {
722 		if (*spec_walk == '/') {
723 			SEPARATE_ZVAL_NOREF(arg);
724 			real_arg = arg;
725 			separate = 1;
726 		} else if (*spec_walk == '!') {
727 			check_null = 1;
728 		} else {
729 			break;
730 		}
731 		spec_walk++;
732 	}
733 
734 	switch (c) {
735 		case 'l':
736 			{
737 				zend_long *p = va_arg(*va, zend_long *);
738 				bool *is_null = NULL;
739 
740 				if (check_null) {
741 					is_null = va_arg(*va, bool *);
742 				}
743 
744 				if (!zend_parse_arg_long(arg, p, is_null, check_null, arg_num)) {
745 					return check_null ? "?int" : "int";
746 				}
747 			}
748 			break;
749 
750 		case 'd':
751 			{
752 				double *p = va_arg(*va, double *);
753 				bool *is_null = NULL;
754 
755 				if (check_null) {
756 					is_null = va_arg(*va, bool *);
757 				}
758 
759 				if (!zend_parse_arg_double(arg, p, is_null, check_null, arg_num)) {
760 					return check_null ? "?float" : "float";
761 				}
762 			}
763 			break;
764 
765 		case 'n':
766 			{
767 				zval **p = va_arg(*va, zval **);
768 
769 				if (!zend_parse_arg_number(arg, p, check_null, arg_num)) {
770 					return check_null ? "int|float|null" : "int|float";
771 				}
772 			}
773 			break;
774 
775 		case 's':
776 			{
777 				char **p = va_arg(*va, char **);
778 				size_t *pl = va_arg(*va, size_t *);
779 				if (!zend_parse_arg_string(arg, p, pl, check_null, arg_num)) {
780 					return check_null ? "?string" : "string";
781 				}
782 			}
783 			break;
784 
785 		case 'p':
786 			{
787 				char **p = va_arg(*va, char **);
788 				size_t *pl = va_arg(*va, size_t *);
789 				if (!zend_parse_arg_path(arg, p, pl, check_null, arg_num)) {
790 					if (Z_TYPE_P(arg) == IS_STRING) {
791 						zend_spprintf(error, 0, "must not contain any null bytes");
792 						return "";
793 					} else {
794 						return check_null ? "?string" : "string";
795 					}
796 				}
797 			}
798 			break;
799 
800 		case 'P':
801 			{
802 				zend_string **str = va_arg(*va, zend_string **);
803 				if (!zend_parse_arg_path_str(arg, str, check_null, arg_num)) {
804 					if (Z_TYPE_P(arg) == IS_STRING) {
805 						zend_spprintf(error, 0, "must not contain any null bytes");
806 						return "";
807 					} else {
808 						return check_null ? "?string" : "string";
809 					}
810 				}
811 			}
812 			break;
813 
814 		case 'S':
815 			{
816 				zend_string **str = va_arg(*va, zend_string **);
817 				if (!zend_parse_arg_str(arg, str, check_null, arg_num)) {
818 					return check_null ? "?string" : "string";
819 				}
820 			}
821 			break;
822 
823 		case 'b':
824 			{
825 				bool *p = va_arg(*va, bool *);
826 				bool *is_null = NULL;
827 
828 				if (check_null) {
829 					is_null = va_arg(*va, bool *);
830 				}
831 
832 				if (!zend_parse_arg_bool(arg, p, is_null, check_null, arg_num)) {
833 					return check_null ? "?bool" : "bool";
834 				}
835 			}
836 			break;
837 
838 		case 'r':
839 			{
840 				zval **p = va_arg(*va, zval **);
841 
842 				if (!zend_parse_arg_resource(arg, p, check_null)) {
843 					return check_null ? "resource or null" : "resource";
844 				}
845 			}
846 			break;
847 
848 		case 'A':
849 		case 'a':
850 			{
851 				zval **p = va_arg(*va, zval **);
852 
853 				if (!zend_parse_arg_array(arg, p, check_null, c == 'A')) {
854 					return check_null ? "?array" : "array";
855 				}
856 			}
857 			break;
858 
859 		case 'H':
860 		case 'h':
861 			{
862 				HashTable **p = va_arg(*va, HashTable **);
863 
864 				if (!zend_parse_arg_array_ht(arg, p, check_null, c == 'H', separate)) {
865 					return check_null ? "?array" : "array";
866 				}
867 			}
868 			break;
869 
870 		case 'o':
871 			{
872 				zval **p = va_arg(*va, zval **);
873 
874 				if (!zend_parse_arg_object(arg, p, NULL, check_null)) {
875 					return check_null ? "?object" : "object";
876 				}
877 			}
878 			break;
879 
880 		case 'O':
881 			{
882 				zval **p = va_arg(*va, zval **);
883 				zend_class_entry *ce = va_arg(*va, zend_class_entry *);
884 
885 				if (!zend_parse_arg_object(arg, p, ce, check_null)) {
886 					if (ce) {
887 						if (check_null) {
888 							zend_spprintf(error, 0, "must be of type ?%s, %s given", ZSTR_VAL(ce->name), zend_zval_type_name(arg));
889 							return "";
890 						} else {
891 							return ZSTR_VAL(ce->name);
892 						}
893 					} else {
894 						return check_null ? "?object" : "object";
895 					}
896 				}
897 			}
898 			break;
899 
900 		case 'C':
901 			{
902 				zend_class_entry *lookup, **pce = va_arg(*va, zend_class_entry **);
903 				zend_class_entry *ce_base = *pce;
904 
905 				if (check_null && Z_TYPE_P(arg) == IS_NULL) {
906 					*pce = NULL;
907 					break;
908 				}
909 				if (!try_convert_to_string(arg)) {
910 					*pce = NULL;
911 					return ""; /* try_convert_to_string() throws an exception */
912 				}
913 
914 				if ((lookup = zend_lookup_class(Z_STR_P(arg))) == NULL) {
915 					*pce = NULL;
916 				} else {
917 					*pce = lookup;
918 				}
919 				if (ce_base) {
920 					if ((!*pce || !instanceof_function(*pce, ce_base))) {
921 						zend_spprintf(error, 0, "must be a class name derived from %s%s, %s given",
922 							ZSTR_VAL(ce_base->name), check_null ? " or null" : "", Z_STRVAL_P(arg));
923 						*pce = NULL;
924 						return "";
925 					}
926 				}
927 				if (!*pce) {
928 					zend_spprintf(error, 0, "must be a valid class name%s, %s given",
929 						check_null ? " or null" : "", Z_STRVAL_P(arg));
930 					return "";
931 				}
932 				break;
933 
934 			}
935 			break;
936 
937 		case 'f':
938 			{
939 				zend_fcall_info *fci = va_arg(*va, zend_fcall_info *);
940 				zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *);
941 				char *is_callable_error = NULL;
942 
943 				if (check_null && Z_TYPE_P(arg) == IS_NULL) {
944 					fci->size = 0;
945 					fcc->function_handler = 0;
946 					break;
947 				}
948 
949 				if (zend_fcall_info_init(arg, 0, fci, fcc, NULL, &is_callable_error) == SUCCESS) {
950 					ZEND_ASSERT(!is_callable_error);
951 					/* Release call trampolines: The function may not get called, in which case
952 					 * the trampoline will leak. Force it to be refetched during
953 					 * zend_call_function instead. */
954 					zend_release_fcall_info_cache(fcc);
955 					break;
956 				}
957 
958 				if (is_callable_error) {
959 					zend_spprintf(error, 0, "must be a valid callback%s, %s", check_null ? " or null" : "", is_callable_error);
960 					efree(is_callable_error);
961 					return "";
962 				} else {
963 					return check_null ? "a valid callback or null" : "a valid callback";
964 				}
965 			}
966 
967 		case 'z':
968 			{
969 				zval **p = va_arg(*va, zval **);
970 
971 				zend_parse_arg_zval_deref(real_arg, p, check_null);
972 			}
973 			break;
974 
975 		case 'Z': /* replace with 'z' */
976 		case 'L': /* replace with 'l' */
977 			ZEND_ASSERT(0 && "ZPP modifier no longer supported");
978 			ZEND_FALLTHROUGH;
979 		default:
980 			return "unknown";
981 	}
982 
983 	*spec = spec_walk;
984 
985 	return NULL;
986 }
987 /* }}} */
988 
zend_parse_arg(uint32_t arg_num,zval * arg,va_list * va,const char ** spec,int flags)989 static zend_result zend_parse_arg(uint32_t arg_num, zval *arg, va_list *va, const char **spec, int flags) /* {{{ */
990 {
991 	const char *expected_type = NULL;
992 	char *error = NULL;
993 
994 	expected_type = zend_parse_arg_impl(arg, va, spec, &error, arg_num);
995 	if (expected_type) {
996 		if (EG(exception)) {
997 			return FAILURE;
998 		}
999 		if (!(flags & ZEND_PARSE_PARAMS_QUIET) && (*expected_type || error)) {
1000 			if (error) {
1001 				if (strcmp(error, "must not contain any null bytes") == 0) {
1002 					zend_argument_value_error(arg_num, "%s", error);
1003 				} else {
1004 					zend_argument_type_error(arg_num, "%s", error);
1005 				}
1006 				efree(error);
1007 			} else {
1008 				zend_argument_type_error(arg_num, "must be of type %s, %s given", expected_type, zend_zval_type_name(arg));
1009 			}
1010 		} else if (error) {
1011 			efree(error);
1012 		}
1013 
1014 		return FAILURE;
1015 	}
1016 
1017 	return SUCCESS;
1018 }
1019 /* }}} */
1020 
zend_parse_parameter(int flags,uint32_t arg_num,zval * arg,const char * spec,...)1021 ZEND_API zend_result zend_parse_parameter(int flags, uint32_t arg_num, zval *arg, const char *spec, ...)
1022 {
1023 	va_list va;
1024 	zend_result ret;
1025 
1026 	va_start(va, spec);
1027 	ret = zend_parse_arg(arg_num, arg, &va, &spec, flags);
1028 	va_end(va);
1029 
1030 	return ret;
1031 }
1032 
zend_parse_parameters_debug_error(const char * msg)1033 static ZEND_COLD void zend_parse_parameters_debug_error(const char *msg) {
1034 	zend_function *active_function = EG(current_execute_data)->func;
1035 	const char *class_name = active_function->common.scope
1036 		? ZSTR_VAL(active_function->common.scope->name) : "";
1037 	zend_error_noreturn(E_CORE_ERROR, "%s%s%s(): %s",
1038 		class_name, class_name[0] ? "::" : "",
1039 		ZSTR_VAL(active_function->common.function_name), msg);
1040 }
1041 
zend_parse_va_args(uint32_t num_args,const char * type_spec,va_list * va,int flags)1042 static zend_result zend_parse_va_args(uint32_t num_args, const char *type_spec, va_list *va, int flags) /* {{{ */
1043 {
1044 	const  char *spec_walk;
1045 	char c;
1046 	uint32_t i;
1047 	uint32_t min_num_args = 0;
1048 	uint32_t max_num_args = 0;
1049 	uint32_t post_varargs = 0;
1050 	zval *arg;
1051 	bool have_varargs = 0;
1052 	bool have_optional_args = 0;
1053 	zval **varargs = NULL;
1054 	uint32_t *n_varargs = NULL;
1055 
1056 	for (spec_walk = type_spec; *spec_walk; spec_walk++) {
1057 		c = *spec_walk;
1058 		switch (c) {
1059 			case 'l': case 'd':
1060 			case 's': case 'b':
1061 			case 'r': case 'a':
1062 			case 'o': case 'O':
1063 			case 'z': case 'Z':
1064 			case 'C': case 'h':
1065 			case 'f': case 'A':
1066 			case 'H': case 'p':
1067 			case 'S': case 'P':
1068 			case 'L': case 'n':
1069 				max_num_args++;
1070 				break;
1071 
1072 			case '|':
1073 				min_num_args = max_num_args;
1074 				have_optional_args = 1;
1075 				break;
1076 
1077 			case '/':
1078 			case '!':
1079 				/* Pass */
1080 				break;
1081 
1082 			case '*':
1083 			case '+':
1084 				if (have_varargs) {
1085 					zend_parse_parameters_debug_error(
1086 						"only one varargs specifier (* or +) is permitted");
1087 					return FAILURE;
1088 				}
1089 				have_varargs = 1;
1090 				/* we expect at least one parameter in varargs */
1091 				if (c == '+') {
1092 					max_num_args++;
1093 				}
1094 				/* mark the beginning of varargs */
1095 				post_varargs = max_num_args;
1096 
1097 				if (ZEND_CALL_INFO(EG(current_execute_data)) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
1098 					zend_unexpected_extra_named_error();
1099 					return FAILURE;
1100 				}
1101 				break;
1102 
1103 			default:
1104 				zend_parse_parameters_debug_error("bad type specifier while parsing parameters");
1105 				return FAILURE;
1106 		}
1107 	}
1108 
1109 	/* with no optional arguments the minimum number of arguments must be the same as the maximum */
1110 	if (!have_optional_args) {
1111 		min_num_args = max_num_args;
1112 	}
1113 
1114 	if (have_varargs) {
1115 		/* calculate how many required args are at the end of the specifier list */
1116 		post_varargs = max_num_args - post_varargs;
1117 		max_num_args = UINT32_MAX;
1118 	}
1119 
1120 	if (num_args < min_num_args || num_args > max_num_args) {
1121 		if (!(flags & ZEND_PARSE_PARAMS_QUIET)) {
1122 			zend_string *func_name = get_active_function_or_method_name();
1123 
1124 			zend_argument_count_error("%s() expects %s %d argument%s, %d given",
1125 				ZSTR_VAL(func_name),
1126 				min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
1127 				num_args < min_num_args ? min_num_args : max_num_args,
1128 				(num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
1129 				num_args
1130 			);
1131 
1132 			zend_string_release(func_name);
1133 		}
1134 		return FAILURE;
1135 	}
1136 
1137 	if (num_args > ZEND_CALL_NUM_ARGS(EG(current_execute_data))) {
1138 		zend_parse_parameters_debug_error("could not obtain parameters for parsing");
1139 		return FAILURE;
1140 	}
1141 
1142 	i = 0;
1143 	while (num_args-- > 0) {
1144 		if (*type_spec == '|') {
1145 			type_spec++;
1146 		}
1147 
1148 		if (*type_spec == '*' || *type_spec == '+') {
1149 			uint32_t num_varargs = num_args + 1 - post_varargs;
1150 
1151 			/* eat up the passed in storage even if it won't be filled in with varargs */
1152 			varargs = va_arg(*va, zval **);
1153 			n_varargs = va_arg(*va, uint32_t *);
1154 			type_spec++;
1155 
1156 			if (num_varargs > 0) {
1157 				*n_varargs = num_varargs;
1158 				*varargs = ZEND_CALL_ARG(EG(current_execute_data), i + 1);
1159 				/* adjust how many args we have left and restart loop */
1160 				num_args += 1 - num_varargs;
1161 				i += num_varargs;
1162 				continue;
1163 			} else {
1164 				*varargs = NULL;
1165 				*n_varargs = 0;
1166 			}
1167 		}
1168 
1169 		arg = ZEND_CALL_ARG(EG(current_execute_data), i + 1);
1170 
1171 		if (zend_parse_arg(i+1, arg, va, &type_spec, flags) == FAILURE) {
1172 			/* clean up varargs array if it was used */
1173 			if (varargs && *varargs) {
1174 				*varargs = NULL;
1175 			}
1176 			return FAILURE;
1177 		}
1178 		i++;
1179 	}
1180 
1181 	return SUCCESS;
1182 }
1183 /* }}} */
1184 
zend_parse_parameters_ex(int flags,uint32_t num_args,const char * type_spec,...)1185 ZEND_API zend_result zend_parse_parameters_ex(int flags, uint32_t num_args, const char *type_spec, ...) /* {{{ */
1186 {
1187 	va_list va;
1188 	zend_result retval;
1189 
1190 	va_start(va, type_spec);
1191 	retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1192 	va_end(va);
1193 
1194 	return retval;
1195 }
1196 /* }}} */
1197 
zend_parse_parameters(uint32_t num_args,const char * type_spec,...)1198 ZEND_API zend_result zend_parse_parameters(uint32_t num_args, const char *type_spec, ...) /* {{{ */
1199 {
1200 	va_list va;
1201 	zend_result retval;
1202 	int flags = 0;
1203 
1204 	va_start(va, type_spec);
1205 	retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1206 	va_end(va);
1207 
1208 	return retval;
1209 }
1210 /* }}} */
1211 
zend_parse_method_parameters(uint32_t num_args,zval * this_ptr,const char * type_spec,...)1212 ZEND_API zend_result zend_parse_method_parameters(uint32_t num_args, zval *this_ptr, const char *type_spec, ...) /* {{{ */
1213 {
1214 	va_list va;
1215 	zend_result retval;
1216 	int flags = 0;
1217 	const char *p = type_spec;
1218 	zval **object;
1219 	zend_class_entry *ce;
1220 
1221 	/* Just checking this_ptr is not enough, because fcall_common_helper does not set
1222 	 * Z_OBJ(EG(This)) to NULL when calling an internal function with common.scope == NULL.
1223 	 * In that case EG(This) would still be the $this from the calling code and we'd take the
1224 	 * wrong branch here. */
1225 	bool is_method = EG(current_execute_data)->func->common.scope != NULL;
1226 
1227 	if (!is_method || !this_ptr || Z_TYPE_P(this_ptr) != IS_OBJECT) {
1228 		va_start(va, type_spec);
1229 		retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1230 		va_end(va);
1231 	} else {
1232 		p++;
1233 
1234 		va_start(va, type_spec);
1235 
1236 		object = va_arg(va, zval **);
1237 		ce = va_arg(va, zend_class_entry *);
1238 		*object = this_ptr;
1239 
1240 		if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce)) {
1241 			zend_error_noreturn(E_CORE_ERROR, "%s::%s() must be derived from %s::%s()",
1242 				ZSTR_VAL(Z_OBJCE_P(this_ptr)->name), get_active_function_name(), ZSTR_VAL(ce->name), get_active_function_name());
1243 		}
1244 
1245 		retval = zend_parse_va_args(num_args, p, &va, flags);
1246 		va_end(va);
1247 	}
1248 	return retval;
1249 }
1250 /* }}} */
1251 
zend_parse_method_parameters_ex(int flags,uint32_t num_args,zval * this_ptr,const char * type_spec,...)1252 ZEND_API zend_result zend_parse_method_parameters_ex(int flags, uint32_t num_args, zval *this_ptr, const char *type_spec, ...) /* {{{ */
1253 {
1254 	va_list va;
1255 	zend_result retval;
1256 	const char *p = type_spec;
1257 	zval **object;
1258 	zend_class_entry *ce;
1259 
1260 	if (!this_ptr) {
1261 		va_start(va, type_spec);
1262 		retval = zend_parse_va_args(num_args, type_spec, &va, flags);
1263 		va_end(va);
1264 	} else {
1265 		p++;
1266 		va_start(va, type_spec);
1267 
1268 		object = va_arg(va, zval **);
1269 		ce = va_arg(va, zend_class_entry *);
1270 		*object = this_ptr;
1271 
1272 		if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce)) {
1273 			if (!(flags & ZEND_PARSE_PARAMS_QUIET)) {
1274 				zend_error_noreturn(E_CORE_ERROR, "%s::%s() must be derived from %s::%s()",
1275 					ZSTR_VAL(ce->name), get_active_function_name(), ZSTR_VAL(Z_OBJCE_P(this_ptr)->name), get_active_function_name());
1276 			}
1277 			va_end(va);
1278 			return FAILURE;
1279 		}
1280 
1281 		retval = zend_parse_va_args(num_args, p, &va, flags);
1282 		va_end(va);
1283 	}
1284 	return retval;
1285 }
1286 /* }}} */
1287 
1288 /* This function should be called after the constructor has been called
1289  * because it may call __set from the uninitialized object otherwise. */
zend_merge_properties(zval * obj,HashTable * properties)1290 ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */
1291 {
1292 	zend_object *zobj = Z_OBJ_P(obj);
1293 	zend_object_write_property_t write_property = zobj->handlers->write_property;
1294 	zend_class_entry *old_scope = EG(fake_scope);
1295 	zend_string *key;
1296 	zval *value;
1297 
1298 	if (HT_IS_PACKED(properties)) {
1299 		return;
1300 	}
1301 	EG(fake_scope) = Z_OBJCE_P(obj);
1302 	ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(properties, key, value) {
1303 		if (key) {
1304 			write_property(zobj, key, value, NULL);
1305 		}
1306 	} ZEND_HASH_FOREACH_END();
1307 	EG(fake_scope) = old_scope;
1308 }
1309 /* }}} */
1310 
zend_allocate_mutable_data(zend_class_entry * class_type)1311 static zend_class_mutable_data *zend_allocate_mutable_data(zend_class_entry *class_type) /* {{{ */
1312 {
1313 	zend_class_mutable_data *mutable_data;
1314 
1315 	ZEND_ASSERT(ZEND_MAP_PTR(class_type->mutable_data) != NULL);
1316 	ZEND_ASSERT(ZEND_MAP_PTR_GET_IMM(class_type->mutable_data) == NULL);
1317 
1318 	mutable_data = zend_arena_alloc(&CG(arena), sizeof(zend_class_mutable_data));
1319 	memset(mutable_data, 0, sizeof(zend_class_mutable_data));
1320 	mutable_data->ce_flags = class_type->ce_flags;
1321 	ZEND_MAP_PTR_SET_IMM(class_type->mutable_data, mutable_data);
1322 
1323 	return mutable_data;
1324 }
1325 /* }}} */
1326 
zend_separate_class_constants_table(zend_class_entry * class_type)1327 ZEND_API HashTable *zend_separate_class_constants_table(zend_class_entry *class_type) /* {{{ */
1328 {
1329 	zend_class_mutable_data *mutable_data;
1330 	HashTable *constants_table;
1331 	zend_string *key;
1332 	zend_class_constant *new_c, *c;
1333 
1334 	constants_table = zend_arena_alloc(&CG(arena), sizeof(HashTable));
1335 	zend_hash_init(constants_table, zend_hash_num_elements(&class_type->constants_table), NULL, NULL, 0);
1336 	zend_hash_extend(constants_table, zend_hash_num_elements(&class_type->constants_table), 0);
1337 
1338 	ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&class_type->constants_table, key, c) {
1339 		if (c->ce == class_type) {
1340 			if (Z_TYPE(c->value) == IS_CONSTANT_AST) {
1341 				new_c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
1342 				memcpy(new_c, c, sizeof(zend_class_constant));
1343 				c = new_c;
1344 			}
1345 			Z_TRY_ADDREF(c->value);
1346 		} else {
1347 			if (Z_TYPE(c->value) == IS_CONSTANT_AST) {
1348 				c = zend_hash_find_ptr(CE_CONSTANTS_TABLE(c->ce), key);
1349 				ZEND_ASSERT(c);
1350 			}
1351 		}
1352 		_zend_hash_append_ptr(constants_table, key, c);
1353 	} ZEND_HASH_FOREACH_END();
1354 
1355 	ZEND_ASSERT(ZEND_MAP_PTR(class_type->mutable_data) != NULL);
1356 
1357 	mutable_data = ZEND_MAP_PTR_GET_IMM(class_type->mutable_data);
1358 	if (!mutable_data) {
1359 		mutable_data = zend_allocate_mutable_data(class_type);
1360 	}
1361 
1362 	mutable_data->constants_table = constants_table;
1363 
1364 	return constants_table;
1365 }
1366 
update_property(zval * val,zend_property_info * prop_info)1367 static zend_result update_property(zval *val, zend_property_info *prop_info) {
1368 	if (ZEND_TYPE_IS_SET(prop_info->type)) {
1369 		zval tmp;
1370 
1371 		ZVAL_COPY(&tmp, val);
1372 		if (UNEXPECTED(zval_update_constant_ex(&tmp, prop_info->ce) != SUCCESS)) {
1373 			zval_ptr_dtor(&tmp);
1374 			return FAILURE;
1375 		}
1376 		/* property initializers must always be evaluated with strict types */;
1377 		if (UNEXPECTED(!zend_verify_property_type(prop_info, &tmp, /* strict */ 1))) {
1378 			zval_ptr_dtor(&tmp);
1379 			return FAILURE;
1380 		}
1381 		zval_ptr_dtor(val);
1382 		ZVAL_COPY_VALUE(val, &tmp);
1383 		return SUCCESS;
1384 	}
1385 	return zval_update_constant_ex(val, prop_info->ce);
1386 }
1387 
zend_update_class_constants(zend_class_entry * class_type)1388 ZEND_API zend_result zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
1389 {
1390 	zend_class_mutable_data *mutable_data = NULL;
1391 	zval *default_properties_table = NULL;
1392 	zval *static_members_table = NULL;
1393 	zend_class_constant *c;
1394 	zval *val;
1395 	uint32_t ce_flags;
1396 
1397 	ce_flags = class_type->ce_flags;
1398 
1399 	if (ce_flags & ZEND_ACC_CONSTANTS_UPDATED) {
1400 		return SUCCESS;
1401 	}
1402 
1403 	bool uses_mutable_data = ZEND_MAP_PTR(class_type->mutable_data) != NULL;
1404 	if (uses_mutable_data) {
1405 		mutable_data = ZEND_MAP_PTR_GET_IMM(class_type->mutable_data);
1406 		if (mutable_data) {
1407 			ce_flags = mutable_data->ce_flags;
1408 			if (ce_flags & ZEND_ACC_CONSTANTS_UPDATED) {
1409 				return SUCCESS;
1410 			}
1411 		} else {
1412 			mutable_data = zend_allocate_mutable_data(class_type);
1413 		}
1414 	}
1415 
1416 	if (class_type->parent) {
1417 		if (UNEXPECTED(zend_update_class_constants(class_type->parent) != SUCCESS)) {
1418 			return FAILURE;
1419 		}
1420 	}
1421 
1422 	if (ce_flags & ZEND_ACC_HAS_AST_CONSTANTS) {
1423 		HashTable *constants_table;
1424 
1425 		if (uses_mutable_data) {
1426 			constants_table = mutable_data->constants_table;
1427 			if (!constants_table) {
1428 				constants_table = zend_separate_class_constants_table(class_type);
1429 			}
1430 		} else {
1431 			constants_table = &class_type->constants_table;
1432 		}
1433 
1434 		zend_string *name;
1435 		ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(constants_table, name, val) {
1436 			c = Z_PTR_P(val);
1437 			if (Z_TYPE(c->value) == IS_CONSTANT_AST) {
1438 				if (c->ce != class_type) {
1439 					Z_PTR_P(val) = c = zend_hash_find_ptr(CE_CONSTANTS_TABLE(c->ce), name);
1440 					if (Z_TYPE(c->value) != IS_CONSTANT_AST) {
1441 						continue;
1442 					}
1443 				}
1444 
1445 				val = &c->value;
1446 				if (UNEXPECTED(zval_update_constant_ex(val, c->ce) != SUCCESS)) {
1447 					return FAILURE;
1448 				}
1449 			}
1450 		} ZEND_HASH_FOREACH_END();
1451 	}
1452 
1453 	if (class_type->default_static_members_count) {
1454 		static_members_table = CE_STATIC_MEMBERS(class_type);
1455 		if (!static_members_table) {
1456 			zend_class_init_statics(class_type);
1457 			static_members_table = CE_STATIC_MEMBERS(class_type);
1458 		}
1459 	}
1460 
1461 	default_properties_table = class_type->default_properties_table;
1462 	if (uses_mutable_data && (ce_flags & ZEND_ACC_HAS_AST_PROPERTIES)) {
1463 		zval *src, *dst, *end;
1464 
1465 		default_properties_table = mutable_data->default_properties_table;
1466 		if (!default_properties_table) {
1467 			default_properties_table = zend_arena_alloc(&CG(arena), sizeof(zval) * class_type->default_properties_count);
1468 			src = class_type->default_properties_table;
1469 			dst = default_properties_table;
1470 			end = dst + class_type->default_properties_count;
1471 			do {
1472 				ZVAL_COPY_PROP(dst, src);
1473 				src++;
1474 				dst++;
1475 			} while (dst != end);
1476 			mutable_data->default_properties_table = default_properties_table;
1477 		}
1478 	}
1479 
1480 	if (ce_flags & (ZEND_ACC_HAS_AST_PROPERTIES|ZEND_ACC_HAS_AST_STATICS)) {
1481 		zend_property_info *prop_info;
1482 
1483 		/* Use the default properties table to also update initializers of private properties
1484 		 * that have been shadowed in a child class. */
1485 		for (uint32_t i = 0; i < class_type->default_properties_count; i++) {
1486 			val = &default_properties_table[i];
1487 			prop_info = class_type->properties_info_table[i];
1488 			if (Z_TYPE_P(val) == IS_CONSTANT_AST
1489 					&& UNEXPECTED(update_property(val, prop_info) != SUCCESS)) {
1490 				return FAILURE;
1491 			}
1492 		}
1493 
1494 		if (class_type->default_static_members_count) {
1495 			ZEND_HASH_MAP_FOREACH_PTR(&class_type->properties_info, prop_info) {
1496 				if (prop_info->flags & ZEND_ACC_STATIC) {
1497 					val = static_members_table + prop_info->offset;
1498 					if (Z_TYPE_P(val) == IS_CONSTANT_AST
1499 							&& UNEXPECTED(update_property(val, prop_info) != SUCCESS)) {
1500 						return FAILURE;
1501 					}
1502 				}
1503 			} ZEND_HASH_FOREACH_END();
1504 		}
1505 	}
1506 
1507 	if (class_type->type == ZEND_USER_CLASS && class_type->ce_flags & ZEND_ACC_ENUM && class_type->enum_backing_type != IS_UNDEF) {
1508 		if (zend_enum_build_backed_enum_table(class_type) == FAILURE) {
1509 			return FAILURE;
1510 		}
1511 	}
1512 
1513 	ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
1514 	ce_flags &= ~ZEND_ACC_HAS_AST_CONSTANTS;
1515 	ce_flags &= ~ZEND_ACC_HAS_AST_PROPERTIES;
1516 	ce_flags &= ~ZEND_ACC_HAS_AST_STATICS;
1517 	if (uses_mutable_data) {
1518 		mutable_data->ce_flags = ce_flags;
1519 	} else {
1520 		class_type->ce_flags = ce_flags;
1521 	}
1522 
1523 	return SUCCESS;
1524 }
1525 /* }}} */
1526 
_object_properties_init(zend_object * object,zend_class_entry * class_type)1527 static zend_always_inline void _object_properties_init(zend_object *object, zend_class_entry *class_type) /* {{{ */
1528 {
1529 	if (class_type->default_properties_count) {
1530 		zval *src = CE_DEFAULT_PROPERTIES_TABLE(class_type);
1531 		zval *dst = object->properties_table;
1532 		zval *end = src + class_type->default_properties_count;
1533 
1534 		if (UNEXPECTED(class_type->type == ZEND_INTERNAL_CLASS)) {
1535 			do {
1536 				ZVAL_COPY_OR_DUP_PROP(dst, src);
1537 				src++;
1538 				dst++;
1539 			} while (src != end);
1540 		} else {
1541 			do {
1542 				ZVAL_COPY_PROP(dst, src);
1543 				src++;
1544 				dst++;
1545 			} while (src != end);
1546 		}
1547 	}
1548 }
1549 /* }}} */
1550 
object_properties_init(zend_object * object,zend_class_entry * class_type)1551 ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type) /* {{{ */
1552 {
1553 	object->properties = NULL;
1554 	_object_properties_init(object, class_type);
1555 }
1556 /* }}} */
1557 
object_properties_init_ex(zend_object * object,HashTable * properties)1558 ZEND_API void object_properties_init_ex(zend_object *object, HashTable *properties) /* {{{ */
1559 {
1560 	object->properties = properties;
1561 	if (object->ce->default_properties_count) {
1562 		zval *prop;
1563 		zend_string *key;
1564 		zend_property_info *property_info;
1565 
1566 		ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(properties, key, prop) {
1567 			property_info = zend_get_property_info(object->ce, key, 1);
1568 			if (property_info != ZEND_WRONG_PROPERTY_INFO &&
1569 			    property_info &&
1570 			    (property_info->flags & ZEND_ACC_STATIC) == 0) {
1571 				zval *slot = OBJ_PROP(object, property_info->offset);
1572 
1573 				if (UNEXPECTED(ZEND_TYPE_IS_SET(property_info->type))) {
1574 					zval tmp;
1575 
1576 					ZVAL_COPY_VALUE(&tmp, prop);
1577 					if (UNEXPECTED(!zend_verify_property_type(property_info, &tmp, 0))) {
1578 						continue;
1579 					}
1580 					ZVAL_COPY_VALUE(slot, &tmp);
1581 				} else {
1582 					ZVAL_COPY_VALUE(slot, prop);
1583 				}
1584 				ZVAL_INDIRECT(prop, slot);
1585 			}
1586 		} ZEND_HASH_FOREACH_END();
1587 	}
1588 }
1589 /* }}} */
1590 
object_properties_load(zend_object * object,HashTable * properties)1591 ZEND_API void object_properties_load(zend_object *object, HashTable *properties) /* {{{ */
1592 {
1593 	zval *prop, tmp;
1594 	zend_string *key;
1595 	zend_long h;
1596 	zend_property_info *property_info;
1597 
1598 	ZEND_HASH_FOREACH_KEY_VAL(properties, h, key, prop) {
1599 		if (key) {
1600 			if (ZSTR_VAL(key)[0] == '\0') {
1601 				const char *class_name, *prop_name;
1602 				size_t prop_name_len;
1603 				if (zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_name_len) == SUCCESS) {
1604 					zend_string *pname = zend_string_init(prop_name, prop_name_len, 0);
1605 					zend_class_entry *prev_scope = EG(fake_scope);
1606 					if (class_name && class_name[0] != '*') {
1607 						zend_string *cname = zend_string_init(class_name, strlen(class_name), 0);
1608 						EG(fake_scope) = zend_lookup_class(cname);
1609 						zend_string_release_ex(cname, 0);
1610 					}
1611 					property_info = zend_get_property_info(object->ce, pname, 1);
1612 					zend_string_release_ex(pname, 0);
1613 					EG(fake_scope) = prev_scope;
1614 				} else {
1615 					property_info = ZEND_WRONG_PROPERTY_INFO;
1616 				}
1617 			} else {
1618 				property_info = zend_get_property_info(object->ce, key, 1);
1619 			}
1620 			if (property_info != ZEND_WRONG_PROPERTY_INFO &&
1621 				property_info &&
1622 				(property_info->flags & ZEND_ACC_STATIC) == 0) {
1623 				zval *slot = OBJ_PROP(object, property_info->offset);
1624 				zval_ptr_dtor(slot);
1625 				ZVAL_COPY_VALUE(slot, prop);
1626 				zval_add_ref(slot);
1627 				if (object->properties) {
1628 					ZVAL_INDIRECT(&tmp, slot);
1629 					zend_hash_update(object->properties, key, &tmp);
1630 				}
1631 			} else {
1632 				if (UNEXPECTED(object->ce->ce_flags & ZEND_ACC_NO_DYNAMIC_PROPERTIES)) {
1633 					zend_throw_error(NULL, "Cannot create dynamic property %s::$%s",
1634 						ZSTR_VAL(object->ce->name), property_info != ZEND_WRONG_PROPERTY_INFO ? zend_get_unmangled_property_name(key): "");
1635 					return;
1636 				} else if (!(object->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
1637 					zend_error(E_DEPRECATED, "Creation of dynamic property %s::$%s is deprecated",
1638 						ZSTR_VAL(object->ce->name), property_info != ZEND_WRONG_PROPERTY_INFO ? zend_get_unmangled_property_name(key): "");
1639 				}
1640 
1641 				if (!object->properties) {
1642 					rebuild_object_properties(object);
1643 				}
1644 				prop = zend_hash_update(object->properties, key, prop);
1645 				zval_add_ref(prop);
1646 			}
1647 		} else {
1648 			if (UNEXPECTED(object->ce->ce_flags & ZEND_ACC_NO_DYNAMIC_PROPERTIES)) {
1649 				zend_throw_error(NULL, "Cannot create dynamic property %s::$" ZEND_LONG_FMT, ZSTR_VAL(object->ce->name), h);
1650 				return;
1651 			} else if (!(object->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
1652 				zend_error(E_DEPRECATED, "Creation of dynamic property %s::$" ZEND_LONG_FMT " is deprecated",
1653 					ZSTR_VAL(object->ce->name), h);
1654 			}
1655 
1656 			if (!object->properties) {
1657 				rebuild_object_properties(object);
1658 			}
1659 			prop = zend_hash_index_update(object->properties, h, prop);
1660 			zval_add_ref(prop);
1661 		}
1662 	} ZEND_HASH_FOREACH_END();
1663 }
1664 /* }}} */
1665 
1666 /* This function requires 'properties' to contain all props declared in the
1667  * class and all props being public. If only a subset is given or the class
1668  * has protected members then you need to merge the properties separately by
1669  * calling zend_merge_properties(). */
_object_and_properties_init(zval * arg,zend_class_entry * class_type,HashTable * properties)1670 static zend_always_inline zend_result _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties) /* {{{ */
1671 {
1672 	if (UNEXPECTED(class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS|ZEND_ACC_ENUM))) {
1673 		if (class_type->ce_flags & ZEND_ACC_INTERFACE) {
1674 			zend_throw_error(NULL, "Cannot instantiate interface %s", ZSTR_VAL(class_type->name));
1675 		} else if (class_type->ce_flags & ZEND_ACC_TRAIT) {
1676 			zend_throw_error(NULL, "Cannot instantiate trait %s", ZSTR_VAL(class_type->name));
1677 		} else if (class_type->ce_flags & ZEND_ACC_ENUM) {
1678 			zend_throw_error(NULL, "Cannot instantiate enum %s", ZSTR_VAL(class_type->name));
1679 		} else {
1680 			zend_throw_error(NULL, "Cannot instantiate abstract class %s", ZSTR_VAL(class_type->name));
1681 		}
1682 		ZVAL_NULL(arg);
1683 		Z_OBJ_P(arg) = NULL;
1684 		return FAILURE;
1685 	}
1686 
1687 	if (UNEXPECTED(!(class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
1688 		if (UNEXPECTED(zend_update_class_constants(class_type) != SUCCESS)) {
1689 			ZVAL_NULL(arg);
1690 			Z_OBJ_P(arg) = NULL;
1691 			return FAILURE;
1692 		}
1693 	}
1694 
1695 	if (class_type->create_object == NULL) {
1696 		zend_object *obj = zend_objects_new(class_type);
1697 
1698 		ZVAL_OBJ(arg, obj);
1699 		if (properties) {
1700 			object_properties_init_ex(obj, properties);
1701 		} else {
1702 			_object_properties_init(obj, class_type);
1703 		}
1704 	} else {
1705 		ZVAL_OBJ(arg, class_type->create_object(class_type));
1706 	}
1707 	return SUCCESS;
1708 }
1709 /* }}} */
1710 
object_and_properties_init(zval * arg,zend_class_entry * class_type,HashTable * properties)1711 ZEND_API zend_result object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties) /* {{{ */
1712 {
1713 	return _object_and_properties_init(arg, class_type, properties);
1714 }
1715 /* }}} */
1716 
object_init_ex(zval * arg,zend_class_entry * class_type)1717 ZEND_API zend_result object_init_ex(zval *arg, zend_class_entry *class_type) /* {{{ */
1718 {
1719 	return _object_and_properties_init(arg, class_type, NULL);
1720 }
1721 /* }}} */
1722 
object_init(zval * arg)1723 ZEND_API void object_init(zval *arg) /* {{{ */
1724 {
1725 	ZVAL_OBJ(arg, zend_objects_new(zend_standard_class_def));
1726 }
1727 /* }}} */
1728 
add_assoc_long_ex(zval * arg,const char * key,size_t key_len,zend_long n)1729 ZEND_API void add_assoc_long_ex(zval *arg, const char *key, size_t key_len, zend_long n) /* {{{ */
1730 {
1731 	zval tmp;
1732 
1733 	ZVAL_LONG(&tmp, n);
1734 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1735 }
1736 /* }}} */
1737 
add_assoc_null_ex(zval * arg,const char * key,size_t key_len)1738 ZEND_API void add_assoc_null_ex(zval *arg, const char *key, size_t key_len) /* {{{ */
1739 {
1740 	zval tmp;
1741 
1742 	ZVAL_NULL(&tmp);
1743 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1744 }
1745 /* }}} */
1746 
add_assoc_bool_ex(zval * arg,const char * key,size_t key_len,bool b)1747 ZEND_API void add_assoc_bool_ex(zval *arg, const char *key, size_t key_len, bool b) /* {{{ */
1748 {
1749 	zval tmp;
1750 
1751 	ZVAL_BOOL(&tmp, b);
1752 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1753 }
1754 /* }}} */
1755 
add_assoc_resource_ex(zval * arg,const char * key,size_t key_len,zend_resource * r)1756 ZEND_API void add_assoc_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r) /* {{{ */
1757 {
1758 	zval tmp;
1759 
1760 	ZVAL_RES(&tmp, r);
1761 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1762 }
1763 /* }}} */
1764 
add_assoc_double_ex(zval * arg,const char * key,size_t key_len,double d)1765 ZEND_API void add_assoc_double_ex(zval *arg, const char *key, size_t key_len, double d) /* {{{ */
1766 {
1767 	zval tmp;
1768 
1769 	ZVAL_DOUBLE(&tmp, d);
1770 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1771 }
1772 /* }}} */
1773 
add_assoc_str_ex(zval * arg,const char * key,size_t key_len,zend_string * str)1774 ZEND_API void add_assoc_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str) /* {{{ */
1775 {
1776 	zval tmp;
1777 
1778 	ZVAL_STR(&tmp, str);
1779 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1780 }
1781 /* }}} */
1782 
add_assoc_string_ex(zval * arg,const char * key,size_t key_len,const char * str)1783 ZEND_API void add_assoc_string_ex(zval *arg, const char *key, size_t key_len, const char *str) /* {{{ */
1784 {
1785 	zval tmp;
1786 
1787 	ZVAL_STRING(&tmp, str);
1788 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1789 }
1790 /* }}} */
1791 
add_assoc_stringl_ex(zval * arg,const char * key,size_t key_len,const char * str,size_t length)1792 ZEND_API void add_assoc_stringl_ex(zval *arg, const char *key, size_t key_len, const char *str, size_t length) /* {{{ */
1793 {
1794 	zval tmp;
1795 
1796 	ZVAL_STRINGL(&tmp, str, length);
1797 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1798 }
1799 /* }}} */
1800 
add_assoc_array_ex(zval * arg,const char * key,size_t key_len,zend_array * arr)1801 ZEND_API void add_assoc_array_ex(zval *arg, const char *key, size_t key_len, zend_array *arr) /* {{{ */
1802 {
1803 	zval tmp;
1804 
1805 	ZVAL_ARR(&tmp, arr);
1806 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1807 }
1808 /* }}} */
1809 
add_assoc_object_ex(zval * arg,const char * key,size_t key_len,zend_object * obj)1810 ZEND_API void add_assoc_object_ex(zval *arg, const char *key, size_t key_len, zend_object *obj) /* {{{ */
1811 {
1812 	zval tmp;
1813 
1814 	ZVAL_OBJ(&tmp, obj);
1815 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1816 }
1817 /* }}} */
1818 
add_assoc_reference_ex(zval * arg,const char * key,size_t key_len,zend_reference * ref)1819 ZEND_API void add_assoc_reference_ex(zval *arg, const char *key, size_t key_len, zend_reference *ref) /* {{{ */
1820 {
1821 	zval tmp;
1822 
1823 	ZVAL_REF(&tmp, ref);
1824 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1825 }
1826 /* }}} */
1827 
add_assoc_zval_ex(zval * arg,const char * key,size_t key_len,zval * value)1828 ZEND_API void add_assoc_zval_ex(zval *arg, const char *key, size_t key_len, zval *value) /* {{{ */
1829 {
1830 	zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, value);
1831 }
1832 /* }}} */
1833 
add_index_long(zval * arg,zend_ulong index,zend_long n)1834 ZEND_API void add_index_long(zval *arg, zend_ulong index, zend_long n) /* {{{ */
1835 {
1836 	zval tmp;
1837 
1838 	ZVAL_LONG(&tmp, n);
1839 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1840 }
1841 /* }}} */
1842 
add_index_null(zval * arg,zend_ulong index)1843 ZEND_API void add_index_null(zval *arg, zend_ulong index) /* {{{ */
1844 {
1845 	zval tmp;
1846 
1847 	ZVAL_NULL(&tmp);
1848 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1849 }
1850 /* }}} */
1851 
add_index_bool(zval * arg,zend_ulong index,bool b)1852 ZEND_API void add_index_bool(zval *arg, zend_ulong index, bool b) /* {{{ */
1853 {
1854 	zval tmp;
1855 
1856 	ZVAL_BOOL(&tmp, b);
1857 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1858 }
1859 /* }}} */
1860 
add_index_resource(zval * arg,zend_ulong index,zend_resource * r)1861 ZEND_API void add_index_resource(zval *arg, zend_ulong index, zend_resource *r) /* {{{ */
1862 {
1863 	zval tmp;
1864 
1865 	ZVAL_RES(&tmp, r);
1866 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1867 }
1868 /* }}} */
1869 
add_index_double(zval * arg,zend_ulong index,double d)1870 ZEND_API void add_index_double(zval *arg, zend_ulong index, double d) /* {{{ */
1871 {
1872 	zval tmp;
1873 
1874 	ZVAL_DOUBLE(&tmp, d);
1875 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1876 }
1877 /* }}} */
1878 
add_index_str(zval * arg,zend_ulong index,zend_string * str)1879 ZEND_API void add_index_str(zval *arg, zend_ulong index, zend_string *str) /* {{{ */
1880 {
1881 	zval tmp;
1882 
1883 	ZVAL_STR(&tmp, str);
1884 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1885 }
1886 /* }}} */
1887 
add_index_string(zval * arg,zend_ulong index,const char * str)1888 ZEND_API void add_index_string(zval *arg, zend_ulong index, const char *str) /* {{{ */
1889 {
1890 	zval tmp;
1891 
1892 	ZVAL_STRING(&tmp, str);
1893 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1894 }
1895 /* }}} */
1896 
add_index_stringl(zval * arg,zend_ulong index,const char * str,size_t length)1897 ZEND_API void add_index_stringl(zval *arg, zend_ulong index, const char *str, size_t length) /* {{{ */
1898 {
1899 	zval tmp;
1900 
1901 	ZVAL_STRINGL(&tmp, str, length);
1902 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1903 }
1904 /* }}} */
1905 
add_index_array(zval * arg,zend_ulong index,zend_array * arr)1906 ZEND_API void add_index_array(zval *arg, zend_ulong index, zend_array *arr) /* {{{ */
1907 {
1908 	zval tmp;
1909 
1910 	ZVAL_ARR(&tmp, arr);
1911 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1912 }
1913 /* }}} */
1914 
add_index_object(zval * arg,zend_ulong index,zend_object * obj)1915 ZEND_API void add_index_object(zval *arg, zend_ulong index, zend_object *obj) /* {{{ */
1916 {
1917 	zval tmp;
1918 
1919 	ZVAL_OBJ(&tmp, obj);
1920 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1921 }
1922 /* }}} */
1923 
add_index_reference(zval * arg,zend_ulong index,zend_reference * ref)1924 ZEND_API void add_index_reference(zval *arg, zend_ulong index, zend_reference *ref) /* {{{ */
1925 {
1926 	zval tmp;
1927 
1928 	ZVAL_REF(&tmp, ref);
1929 	zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1930 }
1931 /* }}} */
1932 
add_next_index_long(zval * arg,zend_long n)1933 ZEND_API zend_result add_next_index_long(zval *arg, zend_long n) /* {{{ */
1934 {
1935 	zval tmp;
1936 
1937 	ZVAL_LONG(&tmp, n);
1938 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1939 }
1940 /* }}} */
1941 
add_next_index_null(zval * arg)1942 ZEND_API zend_result add_next_index_null(zval *arg) /* {{{ */
1943 {
1944 	zval tmp;
1945 
1946 	ZVAL_NULL(&tmp);
1947 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1948 }
1949 /* }}} */
1950 
add_next_index_bool(zval * arg,bool b)1951 ZEND_API zend_result add_next_index_bool(zval *arg, bool b) /* {{{ */
1952 {
1953 	zval tmp;
1954 
1955 	ZVAL_BOOL(&tmp, b);
1956 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1957 }
1958 /* }}} */
1959 
add_next_index_resource(zval * arg,zend_resource * r)1960 ZEND_API zend_result add_next_index_resource(zval *arg, zend_resource *r) /* {{{ */
1961 {
1962 	zval tmp;
1963 
1964 	ZVAL_RES(&tmp, r);
1965 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1966 }
1967 /* }}} */
1968 
add_next_index_double(zval * arg,double d)1969 ZEND_API zend_result add_next_index_double(zval *arg, double d) /* {{{ */
1970 {
1971 	zval tmp;
1972 
1973 	ZVAL_DOUBLE(&tmp, d);
1974 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1975 }
1976 /* }}} */
1977 
add_next_index_str(zval * arg,zend_string * str)1978 ZEND_API zend_result add_next_index_str(zval *arg, zend_string *str) /* {{{ */
1979 {
1980 	zval tmp;
1981 
1982 	ZVAL_STR(&tmp, str);
1983 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1984 }
1985 /* }}} */
1986 
add_next_index_string(zval * arg,const char * str)1987 ZEND_API zend_result add_next_index_string(zval *arg, const char *str) /* {{{ */
1988 {
1989 	zval tmp;
1990 
1991 	ZVAL_STRING(&tmp, str);
1992 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1993 }
1994 /* }}} */
1995 
add_next_index_stringl(zval * arg,const char * str,size_t length)1996 ZEND_API zend_result add_next_index_stringl(zval *arg, const char *str, size_t length) /* {{{ */
1997 {
1998 	zval tmp;
1999 
2000 	ZVAL_STRINGL(&tmp, str, length);
2001 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
2002 }
2003 /* }}} */
2004 
add_next_index_array(zval * arg,zend_array * arr)2005 ZEND_API zend_result add_next_index_array(zval *arg, zend_array *arr) /* {{{ */
2006 {
2007 	zval tmp;
2008 
2009 	ZVAL_ARR(&tmp, arr);
2010 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
2011 }
2012 /* }}} */
2013 
add_next_index_object(zval * arg,zend_object * obj)2014 ZEND_API zend_result add_next_index_object(zval *arg, zend_object *obj) /* {{{ */
2015 {
2016 	zval tmp;
2017 
2018 	ZVAL_OBJ(&tmp, obj);
2019 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
2020 }
2021 /* }}} */
2022 
add_next_index_reference(zval * arg,zend_reference * ref)2023 ZEND_API zend_result add_next_index_reference(zval *arg, zend_reference *ref) /* {{{ */
2024 {
2025 	zval tmp;
2026 
2027 	ZVAL_REF(&tmp, ref);
2028 	return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
2029 }
2030 /* }}} */
2031 
array_set_zval_key(HashTable * ht,zval * key,zval * value)2032 ZEND_API zend_result array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */
2033 {
2034 	zval *result;
2035 
2036 	switch (Z_TYPE_P(key)) {
2037 		case IS_STRING:
2038 			result = zend_symtable_update(ht, Z_STR_P(key), value);
2039 			break;
2040 		case IS_NULL:
2041 			result = zend_hash_update(ht, ZSTR_EMPTY_ALLOC(), value);
2042 			break;
2043 		case IS_RESOURCE:
2044 			zend_use_resource_as_offset(key);
2045 			result = zend_hash_index_update(ht, Z_RES_HANDLE_P(key), value);
2046 			break;
2047 		case IS_FALSE:
2048 			result = zend_hash_index_update(ht, 0, value);
2049 			break;
2050 		case IS_TRUE:
2051 			result = zend_hash_index_update(ht, 1, value);
2052 			break;
2053 		case IS_LONG:
2054 			result = zend_hash_index_update(ht, Z_LVAL_P(key), value);
2055 			break;
2056 		case IS_DOUBLE:
2057 			result = zend_hash_index_update(ht, zend_dval_to_lval_safe(Z_DVAL_P(key)), value);
2058 			break;
2059 		default:
2060 			zend_type_error("Illegal offset type");
2061 			result = NULL;
2062 	}
2063 
2064 	if (result) {
2065 		Z_TRY_ADDREF_P(result);
2066 		return SUCCESS;
2067 	} else {
2068 		return FAILURE;
2069 	}
2070 }
2071 /* }}} */
2072 
add_property_long_ex(zval * arg,const char * key,size_t key_len,zend_long n)2073 ZEND_API void add_property_long_ex(zval *arg, const char *key, size_t key_len, zend_long n) /* {{{ */
2074 {
2075 	zval tmp;
2076 
2077 	ZVAL_LONG(&tmp, n);
2078 	add_property_zval_ex(arg, key, key_len, &tmp);
2079 }
2080 /* }}} */
2081 
add_property_bool_ex(zval * arg,const char * key,size_t key_len,zend_long b)2082 ZEND_API void add_property_bool_ex(zval *arg, const char *key, size_t key_len, zend_long b) /* {{{ */
2083 {
2084 	zval tmp;
2085 
2086 	ZVAL_BOOL(&tmp, b);
2087 	add_property_zval_ex(arg, key, key_len, &tmp);
2088 }
2089 /* }}} */
2090 
add_property_null_ex(zval * arg,const char * key,size_t key_len)2091 ZEND_API void add_property_null_ex(zval *arg, const char *key, size_t key_len) /* {{{ */
2092 {
2093 	zval tmp;
2094 
2095 	ZVAL_NULL(&tmp);
2096 	add_property_zval_ex(arg, key, key_len, &tmp);
2097 }
2098 /* }}} */
2099 
add_property_resource_ex(zval * arg,const char * key,size_t key_len,zend_resource * r)2100 ZEND_API void add_property_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r) /* {{{ */
2101 {
2102 	zval tmp;
2103 
2104 	ZVAL_RES(&tmp, r);
2105 	add_property_zval_ex(arg, key, key_len, &tmp);
2106 	zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2107 }
2108 /* }}} */
2109 
add_property_double_ex(zval * arg,const char * key,size_t key_len,double d)2110 ZEND_API void add_property_double_ex(zval *arg, const char *key, size_t key_len, double d) /* {{{ */
2111 {
2112 	zval tmp;
2113 
2114 	ZVAL_DOUBLE(&tmp, d);
2115 	add_property_zval_ex(arg, key, key_len, &tmp);
2116 }
2117 /* }}} */
2118 
add_property_str_ex(zval * arg,const char * key,size_t key_len,zend_string * str)2119 ZEND_API void add_property_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str) /* {{{ */
2120 {
2121 	zval tmp;
2122 
2123 	ZVAL_STR(&tmp, str);
2124 	add_property_zval_ex(arg, key, key_len, &tmp);
2125 	zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2126 }
2127 /* }}} */
2128 
add_property_string_ex(zval * arg,const char * key,size_t key_len,const char * str)2129 ZEND_API void add_property_string_ex(zval *arg, const char *key, size_t key_len, const char *str) /* {{{ */
2130 {
2131 	zval tmp;
2132 
2133 	ZVAL_STRING(&tmp, str);
2134 	add_property_zval_ex(arg, key, key_len, &tmp);
2135 	zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2136 }
2137 /* }}} */
2138 
add_property_stringl_ex(zval * arg,const char * key,size_t key_len,const char * str,size_t length)2139 ZEND_API void add_property_stringl_ex(zval *arg, const char *key, size_t key_len, const char *str, size_t length) /* {{{ */
2140 {
2141 	zval tmp;
2142 
2143 	ZVAL_STRINGL(&tmp, str, length);
2144 	add_property_zval_ex(arg, key, key_len, &tmp);
2145 	zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2146 }
2147 /* }}} */
2148 
add_property_array_ex(zval * arg,const char * key,size_t key_len,zend_array * arr)2149 ZEND_API void add_property_array_ex(zval *arg, const char *key, size_t key_len, zend_array *arr) /* {{{ */
2150 {
2151 	zval tmp;
2152 
2153 	ZVAL_ARR(&tmp, arr);
2154 	add_property_zval_ex(arg, key, key_len, &tmp);
2155 	zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2156 }
2157 /* }}} */
2158 
add_property_object_ex(zval * arg,const char * key,size_t key_len,zend_object * obj)2159 ZEND_API void add_property_object_ex(zval *arg, const char *key, size_t key_len, zend_object *obj) /* {{{ */
2160 {
2161 	zval tmp;
2162 
2163 	ZVAL_OBJ(&tmp, obj);
2164 	add_property_zval_ex(arg, key, key_len, &tmp);
2165 	zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2166 }
2167 /* }}} */
2168 
add_property_reference_ex(zval * arg,const char * key,size_t key_len,zend_reference * ref)2169 ZEND_API void add_property_reference_ex(zval *arg, const char *key, size_t key_len, zend_reference *ref) /* {{{ */
2170 {
2171 	zval tmp;
2172 
2173 	ZVAL_REF(&tmp, ref);
2174 	add_property_zval_ex(arg, key, key_len, &tmp);
2175 	zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
2176 }
2177 /* }}} */
2178 
add_property_zval_ex(zval * arg,const char * key,size_t key_len,zval * value)2179 ZEND_API void add_property_zval_ex(zval *arg, const char *key, size_t key_len, zval *value) /* {{{ */
2180 {
2181 	zend_string *str;
2182 
2183 	str = zend_string_init(key, key_len, 0);
2184 	Z_OBJ_HANDLER_P(arg, write_property)(Z_OBJ_P(arg), str, value, NULL);
2185 	zend_string_release_ex(str, 0);
2186 }
2187 /* }}} */
2188 
zend_startup_module_ex(zend_module_entry * module)2189 ZEND_API zend_result zend_startup_module_ex(zend_module_entry *module) /* {{{ */
2190 {
2191 	size_t name_len;
2192 	zend_string *lcname;
2193 
2194 	if (module->module_started) {
2195 		return SUCCESS;
2196 	}
2197 	module->module_started = 1;
2198 
2199 	/* Check module dependencies */
2200 	if (module->deps) {
2201 		const zend_module_dep *dep = module->deps;
2202 
2203 		while (dep->name) {
2204 			if (dep->type == MODULE_DEP_REQUIRED) {
2205 				zend_module_entry *req_mod;
2206 
2207 				name_len = strlen(dep->name);
2208 				lcname = zend_string_alloc(name_len, 0);
2209 				zend_str_tolower_copy(ZSTR_VAL(lcname), dep->name, name_len);
2210 
2211 				if ((req_mod = zend_hash_find_ptr(&module_registry, lcname)) == NULL || !req_mod->module_started) {
2212 					zend_string_efree(lcname);
2213 					/* TODO: Check version relationship */
2214 					zend_error(E_CORE_WARNING, "Cannot load module \"%s\" because required module \"%s\" is not loaded", module->name, dep->name);
2215 					module->module_started = 0;
2216 					return FAILURE;
2217 				}
2218 				zend_string_efree(lcname);
2219 			}
2220 			++dep;
2221 		}
2222 	}
2223 
2224 	/* Initialize module globals */
2225 	if (module->globals_size) {
2226 #ifdef ZTS
2227 		ts_allocate_id(module->globals_id_ptr, module->globals_size, (ts_allocate_ctor) module->globals_ctor, (ts_allocate_dtor) module->globals_dtor);
2228 #else
2229 		if (module->globals_ctor) {
2230 			module->globals_ctor(module->globals_ptr);
2231 		}
2232 #endif
2233 	}
2234 	if (module->module_startup_func) {
2235 		EG(current_module) = module;
2236 		if (module->module_startup_func(module->type, module->module_number)==FAILURE) {
2237 			zend_error_noreturn(E_CORE_ERROR,"Unable to start %s module", module->name);
2238 			EG(current_module) = NULL;
2239 			return FAILURE;
2240 		}
2241 		EG(current_module) = NULL;
2242 	}
2243 	return SUCCESS;
2244 }
2245 /* }}} */
2246 
zend_startup_module_zval(zval * zv)2247 static int zend_startup_module_zval(zval *zv) /* {{{ */
2248 {
2249 	zend_module_entry *module = Z_PTR_P(zv);
2250 
2251 	return (zend_startup_module_ex(module) == SUCCESS) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE;
2252 }
2253 /* }}} */
2254 
zend_sort_modules(void * base,size_t count,size_t siz,compare_func_t compare,swap_func_t swp)2255 static void zend_sort_modules(void *base, size_t count, size_t siz, compare_func_t compare, swap_func_t swp) /* {{{ */
2256 {
2257 	Bucket *b1 = base;
2258 	Bucket *b2;
2259 	Bucket *end = b1 + count;
2260 	Bucket tmp;
2261 	zend_module_entry *m, *r;
2262 
2263 	while (b1 < end) {
2264 try_again:
2265 		m = (zend_module_entry*)Z_PTR(b1->val);
2266 		if (!m->module_started && m->deps) {
2267 			const zend_module_dep *dep = m->deps;
2268 			while (dep->name) {
2269 				if (dep->type == MODULE_DEP_REQUIRED || dep->type == MODULE_DEP_OPTIONAL) {
2270 					b2 = b1 + 1;
2271 					while (b2 < end) {
2272 						r = (zend_module_entry*)Z_PTR(b2->val);
2273 						if (strcasecmp(dep->name, r->name) == 0) {
2274 							tmp = *b1;
2275 							*b1 = *b2;
2276 							*b2 = tmp;
2277 							goto try_again;
2278 						}
2279 						b2++;
2280 					}
2281 				}
2282 				dep++;
2283 			}
2284 		}
2285 		b1++;
2286 	}
2287 }
2288 /* }}} */
2289 
zend_collect_module_handlers(void)2290 ZEND_API void zend_collect_module_handlers(void) /* {{{ */
2291 {
2292 	zend_module_entry *module;
2293 	int startup_count = 0;
2294 	int shutdown_count = 0;
2295 	int post_deactivate_count = 0;
2296 	int dl_loaded_count = 0;
2297 	zend_class_entry *ce;
2298 	int class_count = 0;
2299 
2300 	/* Collect extensions with request startup/shutdown handlers */
2301 	ZEND_HASH_MAP_FOREACH_PTR(&module_registry, module) {
2302 		if (module->request_startup_func) {
2303 			startup_count++;
2304 		}
2305 		if (module->request_shutdown_func) {
2306 			shutdown_count++;
2307 		}
2308 		if (module->post_deactivate_func) {
2309 			post_deactivate_count++;
2310 		}
2311 		if (module->handle) {
2312 			dl_loaded_count++;
2313 		}
2314 	} ZEND_HASH_FOREACH_END();
2315 	module_request_startup_handlers = (zend_module_entry**)realloc(
2316 		module_request_startup_handlers,
2317 	    sizeof(zend_module_entry*) *
2318 		(startup_count + 1 +
2319 		 shutdown_count + 1 +
2320 		 post_deactivate_count + 1));
2321 	module_request_startup_handlers[startup_count] = NULL;
2322 	module_request_shutdown_handlers = module_request_startup_handlers + startup_count + 1;
2323 	module_request_shutdown_handlers[shutdown_count] = NULL;
2324 	module_post_deactivate_handlers = module_request_shutdown_handlers + shutdown_count + 1;
2325 	module_post_deactivate_handlers[post_deactivate_count] = NULL;
2326 	/* Cannot reuse module_request_startup_handlers because it is freed in zend_destroy_modules, which happens before zend_unload_modules. */
2327 	modules_dl_loaded = realloc(modules_dl_loaded, sizeof(zend_module_entry*) * (dl_loaded_count + 1));
2328 	modules_dl_loaded[dl_loaded_count] = NULL;
2329 	startup_count = 0;
2330 
2331 	ZEND_HASH_MAP_FOREACH_PTR(&module_registry, module) {
2332 		if (module->request_startup_func) {
2333 			module_request_startup_handlers[startup_count++] = module;
2334 		}
2335 		if (module->request_shutdown_func) {
2336 			module_request_shutdown_handlers[--shutdown_count] = module;
2337 		}
2338 		if (module->post_deactivate_func) {
2339 			module_post_deactivate_handlers[--post_deactivate_count] = module;
2340 		}
2341 		if (module->handle) {
2342 			modules_dl_loaded[--dl_loaded_count] = module;
2343 		}
2344 	} ZEND_HASH_FOREACH_END();
2345 
2346 	/* Collect internal classes with static members */
2347 	ZEND_HASH_MAP_FOREACH_PTR(CG(class_table), ce) {
2348 		if (ce->type == ZEND_INTERNAL_CLASS &&
2349 		    ce->default_static_members_count > 0) {
2350 		    class_count++;
2351 		}
2352 	} ZEND_HASH_FOREACH_END();
2353 
2354 	class_cleanup_handlers = (zend_class_entry**)realloc(
2355 		class_cleanup_handlers,
2356 		sizeof(zend_class_entry*) *
2357 		(class_count + 1));
2358 	class_cleanup_handlers[class_count] = NULL;
2359 
2360 	if (class_count) {
2361 		ZEND_HASH_MAP_FOREACH_PTR(CG(class_table), ce) {
2362 			if (ce->type == ZEND_INTERNAL_CLASS &&
2363 			    ce->default_static_members_count > 0) {
2364 			    class_cleanup_handlers[--class_count] = ce;
2365 			}
2366 		} ZEND_HASH_FOREACH_END();
2367 	}
2368 }
2369 /* }}} */
2370 
zend_startup_modules(void)2371 ZEND_API void zend_startup_modules(void) /* {{{ */
2372 {
2373 	zend_hash_sort_ex(&module_registry, zend_sort_modules, NULL, 0);
2374 	zend_hash_apply(&module_registry, zend_startup_module_zval);
2375 }
2376 /* }}} */
2377 
zend_destroy_modules(void)2378 ZEND_API void zend_destroy_modules(void) /* {{{ */
2379 {
2380 	free(class_cleanup_handlers);
2381 	class_cleanup_handlers = NULL;
2382 	free(module_request_startup_handlers);
2383 	module_request_startup_handlers = NULL;
2384 	zend_hash_graceful_reverse_destroy(&module_registry);
2385 }
2386 /* }}} */
2387 
zend_register_module_ex(zend_module_entry * module)2388 ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module) /* {{{ */
2389 {
2390 	size_t name_len;
2391 	zend_string *lcname;
2392 	zend_module_entry *module_ptr;
2393 
2394 	if (!module) {
2395 		return NULL;
2396 	}
2397 
2398 #if 0
2399 	zend_printf("%s: Registering module %d\n", module->name, module->module_number);
2400 #endif
2401 
2402 	/* Check module dependencies */
2403 	if (module->deps) {
2404 		const zend_module_dep *dep = module->deps;
2405 
2406 		while (dep->name) {
2407 			if (dep->type == MODULE_DEP_CONFLICTS) {
2408 				name_len = strlen(dep->name);
2409 				lcname = zend_string_alloc(name_len, 0);
2410 				zend_str_tolower_copy(ZSTR_VAL(lcname), dep->name, name_len);
2411 
2412 				if (zend_hash_exists(&module_registry, lcname) || zend_get_extension(dep->name)) {
2413 					zend_string_efree(lcname);
2414 					/* TODO: Check version relationship */
2415 					zend_error(E_CORE_WARNING, "Cannot load module \"%s\" because conflicting module \"%s\" is already loaded", module->name, dep->name);
2416 					return NULL;
2417 				}
2418 				zend_string_efree(lcname);
2419 			}
2420 			++dep;
2421 		}
2422 	}
2423 
2424 	name_len = strlen(module->name);
2425 	lcname = zend_string_alloc(name_len, module->type == MODULE_PERSISTENT);
2426 	zend_str_tolower_copy(ZSTR_VAL(lcname), module->name, name_len);
2427 
2428 	lcname = zend_new_interned_string(lcname);
2429 	if ((module_ptr = zend_hash_add_ptr(&module_registry, lcname, module)) == NULL) {
2430 		zend_error(E_CORE_WARNING, "Module \"%s\" is already loaded", module->name);
2431 		zend_string_release(lcname);
2432 		return NULL;
2433 	}
2434 	module = module_ptr;
2435 	EG(current_module) = module;
2436 
2437 	if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type)==FAILURE) {
2438 		zend_hash_del(&module_registry, lcname);
2439 		zend_string_release(lcname);
2440 		EG(current_module) = NULL;
2441 		zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name);
2442 		return NULL;
2443 	}
2444 
2445 	EG(current_module) = NULL;
2446 	zend_string_release(lcname);
2447 	return module;
2448 }
2449 /* }}} */
2450 
zend_register_internal_module(zend_module_entry * module)2451 ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *module) /* {{{ */
2452 {
2453 	module->module_number = zend_next_free_module();
2454 	module->type = MODULE_PERSISTENT;
2455 	return zend_register_module_ex(module);
2456 }
2457 /* }}} */
2458 
zend_check_magic_method_args(uint32_t num_args,const zend_class_entry * ce,const zend_function * fptr,int error_type)2459 static void zend_check_magic_method_args(
2460 		uint32_t num_args, const zend_class_entry *ce, const zend_function *fptr, int error_type)
2461 {
2462 	if (fptr->common.num_args != num_args) {
2463 		if (num_args == 0) {
2464 			zend_error(error_type, "Method %s::%s() cannot take arguments",
2465 				ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2466 		} else if (num_args == 1) {
2467 			zend_error(error_type, "Method %s::%s() must take exactly 1 argument",
2468 				ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2469 		} else {
2470 			zend_error(error_type, "Method %s::%s() must take exactly %" PRIu32 " arguments",
2471 				ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name), num_args);
2472 		}
2473 		return;
2474 	}
2475 	for (uint32_t i = 0; i < num_args; i++) {
2476 		if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, i + 1)) {
2477 			zend_error(error_type, "Method %s::%s() cannot take arguments by reference",
2478 				ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2479 			return;
2480 		}
2481 	}
2482 }
2483 
zend_check_magic_method_arg_type(uint32_t arg_num,const zend_class_entry * ce,const zend_function * fptr,int error_type,int arg_type)2484 static void zend_check_magic_method_arg_type(uint32_t arg_num, const zend_class_entry *ce, const zend_function *fptr, int error_type, int arg_type)
2485 {
2486 		if (
2487 			ZEND_TYPE_IS_SET(fptr->common.arg_info[arg_num].type)
2488 			 && !(ZEND_TYPE_FULL_MASK(fptr->common.arg_info[arg_num].type) & arg_type)
2489 		) {
2490 			zend_error(error_type, "%s::%s(): Parameter #%d ($%s) must be of type %s when declared",
2491 				ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name),
2492 				arg_num + 1, ZSTR_VAL(fptr->common.arg_info[arg_num].name),
2493 				ZSTR_VAL(zend_type_to_string((zend_type) ZEND_TYPE_INIT_MASK(arg_type))));
2494 		}
2495 }
2496 
zend_check_magic_method_return_type(const zend_class_entry * ce,const zend_function * fptr,int error_type,int return_type)2497 static void zend_check_magic_method_return_type(const zend_class_entry *ce, const zend_function *fptr, int error_type, int return_type)
2498 {
2499 	if (!(fptr->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
2500 		/* For backwards compatibility reasons, do not enforce the return type if it is not set. */
2501 		return;
2502 	}
2503 
2504 	if (ZEND_TYPE_PURE_MASK(fptr->common.arg_info[-1].type) & MAY_BE_NEVER) {
2505 		/* It is always legal to specify the never type. */
2506 		return;
2507 	}
2508 
2509 	bool is_complex_type = ZEND_TYPE_IS_COMPLEX(fptr->common.arg_info[-1].type);
2510 	uint32_t extra_types = ZEND_TYPE_PURE_MASK(fptr->common.arg_info[-1].type) & ~return_type;
2511 	if (extra_types & MAY_BE_STATIC) {
2512 		extra_types &= ~MAY_BE_STATIC;
2513 		is_complex_type = true;
2514 	}
2515 
2516 	if (extra_types || (is_complex_type && return_type != MAY_BE_OBJECT)) {
2517 		zend_error(error_type, "%s::%s(): Return type must be %s when declared",
2518 			ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name),
2519 			ZSTR_VAL(zend_type_to_string((zend_type) ZEND_TYPE_INIT_MASK(return_type))));
2520 	}
2521 }
2522 
zend_check_magic_method_non_static(const zend_class_entry * ce,const zend_function * fptr,int error_type)2523 static void zend_check_magic_method_non_static(
2524 		const zend_class_entry *ce, const zend_function *fptr, int error_type)
2525 {
2526 	if (fptr->common.fn_flags & ZEND_ACC_STATIC) {
2527 		zend_error(error_type, "Method %s::%s() cannot be static",
2528 			ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2529 	}
2530 }
2531 
zend_check_magic_method_static(const zend_class_entry * ce,const zend_function * fptr,int error_type)2532 static void zend_check_magic_method_static(
2533 		const zend_class_entry *ce, const zend_function *fptr, int error_type)
2534 {
2535 	if (!(fptr->common.fn_flags & ZEND_ACC_STATIC)) {
2536 		zend_error(error_type, "Method %s::%s() must be static",
2537 			ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2538 	}
2539 }
2540 
zend_check_magic_method_public(const zend_class_entry * ce,const zend_function * fptr,int error_type)2541 static void zend_check_magic_method_public(
2542 		const zend_class_entry *ce, const zend_function *fptr, int error_type)
2543 {
2544 	// TODO: Remove this warning after adding proper visibility handling.
2545 	if (!(fptr->common.fn_flags & ZEND_ACC_PUBLIC)) {
2546 		zend_error(E_WARNING, "The magic method %s::%s() must have public visibility",
2547 			ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2548 	}
2549 }
2550 
zend_check_magic_method_no_return_type(const zend_class_entry * ce,const zend_function * fptr,int error_type)2551 static void zend_check_magic_method_no_return_type(
2552 		const zend_class_entry *ce, const zend_function *fptr, int error_type)
2553 {
2554 	if (fptr->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
2555 		zend_error_noreturn(error_type, "Method %s::%s() cannot declare a return type",
2556 			ZSTR_VAL(ce->name), ZSTR_VAL(fptr->common.function_name));
2557 	}
2558 }
2559 
zend_check_magic_method_implementation(const zend_class_entry * ce,const zend_function * fptr,zend_string * lcname,int error_type)2560 ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, zend_string *lcname, int error_type) /* {{{ */
2561 {
2562 	if (ZSTR_VAL(lcname)[0] != '_'
2563 	 || ZSTR_VAL(lcname)[1] != '_') {
2564 		return;
2565 	}
2566 
2567 	if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
2568 		zend_check_magic_method_non_static(ce, fptr, error_type);
2569 		zend_check_magic_method_no_return_type(ce, fptr, error_type);
2570 	} else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) {
2571 		zend_check_magic_method_args(0, ce, fptr, error_type);
2572 		zend_check_magic_method_non_static(ce, fptr, error_type);
2573 		zend_check_magic_method_no_return_type(ce, fptr, error_type);
2574 	} else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) {
2575 		zend_check_magic_method_args(0, ce, fptr, error_type);
2576 		zend_check_magic_method_non_static(ce, fptr, error_type);
2577 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
2578 	} else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) {
2579 		zend_check_magic_method_args(1, ce, fptr, error_type);
2580 		zend_check_magic_method_non_static(ce, fptr, error_type);
2581 		zend_check_magic_method_public(ce, fptr, error_type);
2582 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2583 	} else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) {
2584 		zend_check_magic_method_args(2, ce, fptr, error_type);
2585 		zend_check_magic_method_non_static(ce, fptr, error_type);
2586 		zend_check_magic_method_public(ce, fptr, error_type);
2587 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2588 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
2589 	} else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) {
2590 		zend_check_magic_method_args(1, ce, fptr, error_type);
2591 		zend_check_magic_method_non_static(ce, fptr, error_type);
2592 		zend_check_magic_method_public(ce, fptr, error_type);
2593 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2594 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
2595 	} else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
2596 		zend_check_magic_method_args(1, ce, fptr, error_type);
2597 		zend_check_magic_method_non_static(ce, fptr, error_type);
2598 		zend_check_magic_method_public(ce, fptr, error_type);
2599 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2600 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_BOOL);
2601 	} else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
2602 		zend_check_magic_method_args(2, ce, fptr, error_type);
2603 		zend_check_magic_method_non_static(ce, fptr, error_type);
2604 		zend_check_magic_method_public(ce, fptr, error_type);
2605 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2606 		zend_check_magic_method_arg_type(1, ce, fptr, error_type, MAY_BE_ARRAY);
2607 	} else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) {
2608 		zend_check_magic_method_args(2, ce, fptr, error_type);
2609 		zend_check_magic_method_static(ce, fptr, error_type);
2610 		zend_check_magic_method_public(ce, fptr, error_type);
2611 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_STRING);
2612 		zend_check_magic_method_arg_type(1, ce, fptr, error_type, MAY_BE_ARRAY);
2613 	} else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
2614 		zend_check_magic_method_args(0, ce, fptr, error_type);
2615 		zend_check_magic_method_non_static(ce, fptr, error_type);
2616 		zend_check_magic_method_public(ce, fptr, error_type);
2617 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_STRING);
2618 	} else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
2619 		zend_check_magic_method_args(0, ce, fptr, error_type);
2620 		zend_check_magic_method_non_static(ce, fptr, error_type);
2621 		zend_check_magic_method_public(ce, fptr, error_type);
2622 		zend_check_magic_method_return_type(ce, fptr, error_type, (MAY_BE_ARRAY | MAY_BE_NULL));
2623 	} else if (zend_string_equals_literal(lcname, "__serialize")) {
2624 		zend_check_magic_method_args(0, ce, fptr, error_type);
2625 		zend_check_magic_method_non_static(ce, fptr, error_type);
2626 		zend_check_magic_method_public(ce, fptr, error_type);
2627 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_ARRAY);
2628 	} else if (zend_string_equals_literal(lcname, "__unserialize")) {
2629 		zend_check_magic_method_args(1, ce, fptr, error_type);
2630 		zend_check_magic_method_non_static(ce, fptr, error_type);
2631 		zend_check_magic_method_public(ce, fptr, error_type);
2632 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_ARRAY);
2633 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
2634 	} else if (zend_string_equals_literal(lcname, "__set_state")) {
2635 		zend_check_magic_method_args(1, ce, fptr, error_type);
2636 		zend_check_magic_method_static(ce, fptr, error_type);
2637 		zend_check_magic_method_public(ce, fptr, error_type);
2638 		zend_check_magic_method_arg_type(0, ce, fptr, error_type, MAY_BE_ARRAY);
2639 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_OBJECT);
2640 	} else if (zend_string_equals_literal(lcname, "__invoke")) {
2641 		zend_check_magic_method_non_static(ce, fptr, error_type);
2642 		zend_check_magic_method_public(ce, fptr, error_type);
2643 	} else if (zend_string_equals_literal(lcname, "__sleep")) {
2644 		zend_check_magic_method_args(0, ce, fptr, error_type);
2645 		zend_check_magic_method_non_static(ce, fptr, error_type);
2646 		zend_check_magic_method_public(ce, fptr, error_type);
2647 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_ARRAY);
2648 	} else if (zend_string_equals_literal(lcname, "__wakeup")) {
2649 		zend_check_magic_method_args(0, ce, fptr, error_type);
2650 		zend_check_magic_method_non_static(ce, fptr, error_type);
2651 		zend_check_magic_method_public(ce, fptr, error_type);
2652 		zend_check_magic_method_return_type(ce, fptr, error_type, MAY_BE_VOID);
2653 	}
2654 }
2655 /* }}} */
2656 
zend_add_magic_method(zend_class_entry * ce,zend_function * fptr,zend_string * lcname)2657 ZEND_API void zend_add_magic_method(zend_class_entry *ce, zend_function *fptr, zend_string *lcname)
2658 {
2659 	if (ZSTR_VAL(lcname)[0] != '_' || ZSTR_VAL(lcname)[1] != '_') {
2660 		/* pass */
2661 	} else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) {
2662 		ce->clone = fptr;
2663 	} else if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
2664 		ce->constructor = fptr;
2665 		ce->constructor->common.fn_flags |= ZEND_ACC_CTOR;
2666 	} else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) {
2667 		ce->destructor = fptr;
2668 	} else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) {
2669 		ce->__get = fptr;
2670 		ce->ce_flags |= ZEND_ACC_USE_GUARDS;
2671 	} else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) {
2672 		ce->__set = fptr;
2673 		ce->ce_flags |= ZEND_ACC_USE_GUARDS;
2674 	} else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
2675 		ce->__call = fptr;
2676 	} else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) {
2677 		ce->__unset = fptr;
2678 		ce->ce_flags |= ZEND_ACC_USE_GUARDS;
2679 	} else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
2680 		ce->__isset = fptr;
2681 		ce->ce_flags |= ZEND_ACC_USE_GUARDS;
2682 	} else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) {
2683 		ce->__callstatic = fptr;
2684 	} else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
2685 		ce->__tostring = fptr;
2686 	} else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
2687 		ce->__debugInfo = fptr;
2688 	} else if (zend_string_equals_literal(lcname, "__serialize")) {
2689 		ce->__serialize = fptr;
2690 	} else if (zend_string_equals_literal(lcname, "__unserialize")) {
2691 		ce->__unserialize = fptr;
2692 	}
2693 }
2694 
2695 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arg_info_toString, 0, 0, IS_STRING, 0)
ZEND_END_ARG_INFO()2696 ZEND_END_ARG_INFO()
2697 
2698 /* registers all functions in *library_functions in the function hash */
2699 ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type) /* {{{ */
2700 {
2701 	const zend_function_entry *ptr = functions;
2702 	zend_function function, *reg_function;
2703 	zend_internal_function *internal_function = (zend_internal_function *)&function;
2704 	int count=0, unload=0;
2705 	HashTable *target_function_table = function_table;
2706 	int error_type;
2707 	zend_string *lowercase_name;
2708 	size_t fname_len;
2709 
2710 	if (type==MODULE_PERSISTENT) {
2711 		error_type = E_CORE_WARNING;
2712 	} else {
2713 		error_type = E_WARNING;
2714 	}
2715 
2716 	if (!target_function_table) {
2717 		target_function_table = CG(function_table);
2718 	}
2719 	internal_function->type = ZEND_INTERNAL_FUNCTION;
2720 	internal_function->module = EG(current_module);
2721 	internal_function->T = 0;
2722 	memset(internal_function->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*));
2723 
2724 	while (ptr->fname) {
2725 		fname_len = strlen(ptr->fname);
2726 		internal_function->handler = ptr->handler;
2727 		internal_function->function_name = zend_string_init_interned(ptr->fname, fname_len, 1);
2728 		internal_function->scope = scope;
2729 		internal_function->prototype = NULL;
2730 		internal_function->attributes = NULL;
2731 		if (EG(active)) { // at run-time: this ought to only happen if registered with dl() or somehow temporarily at runtime
2732 			ZEND_MAP_PTR_INIT(internal_function->run_time_cache, zend_arena_calloc(&CG(arena), 1, zend_internal_run_time_cache_reserved_size()));
2733 		} else {
2734 			ZEND_MAP_PTR_NEW(internal_function->run_time_cache);
2735 		}
2736 		if (ptr->flags) {
2737 			if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
2738 				if (ptr->flags != ZEND_ACC_DEPRECATED && scope) {
2739 					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);
2740 				}
2741 				internal_function->fn_flags = ZEND_ACC_PUBLIC | ptr->flags;
2742 			} else {
2743 				internal_function->fn_flags = ptr->flags;
2744 			}
2745 		} else {
2746 			internal_function->fn_flags = ZEND_ACC_PUBLIC;
2747 		}
2748 
2749 		if (ptr->arg_info) {
2750 			zend_internal_function_info *info = (zend_internal_function_info*)ptr->arg_info;
2751 			internal_function->arg_info = (zend_internal_arg_info*)ptr->arg_info+1;
2752 			internal_function->num_args = ptr->num_args;
2753 			/* Currently you cannot denote that the function can accept less arguments than num_args */
2754 			if (info->required_num_args == (zend_uintptr_t)-1) {
2755 				internal_function->required_num_args = ptr->num_args;
2756 			} else {
2757 				internal_function->required_num_args = info->required_num_args;
2758 			}
2759 			if (ZEND_ARG_SEND_MODE(info)) {
2760 				internal_function->fn_flags |= ZEND_ACC_RETURN_REFERENCE;
2761 			}
2762 			if (ZEND_ARG_IS_VARIADIC(&ptr->arg_info[ptr->num_args])) {
2763 				internal_function->fn_flags |= ZEND_ACC_VARIADIC;
2764 				/* Don't count the variadic argument */
2765 				internal_function->num_args--;
2766 			}
2767 			if (ZEND_TYPE_IS_SET(info->type)) {
2768 				if (ZEND_TYPE_HAS_NAME(info->type)) {
2769 					const char *type_name = ZEND_TYPE_LITERAL_NAME(info->type);
2770 					if (!scope && (!strcasecmp(type_name, "self") || !strcasecmp(type_name, "parent"))) {
2771 						zend_error_noreturn(E_CORE_ERROR, "Cannot declare a return type of %s outside of a class scope", type_name);
2772 					}
2773 				}
2774 
2775 				internal_function->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
2776 			}
2777 		} else {
2778 			zend_error(E_CORE_WARNING, "Missing arginfo for %s%s%s()",
2779 				 scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2780 
2781 			internal_function->arg_info = NULL;
2782 			internal_function->num_args = 0;
2783 			internal_function->required_num_args = 0;
2784 		}
2785 
2786 		/* If not specified, add __toString() return type for compatibility with Stringable
2787 		 * interface. */
2788 		if (scope && zend_string_equals_literal_ci(internal_function->function_name, "__tostring") &&
2789 				!(internal_function->fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
2790 			zend_error(E_CORE_WARNING, "%s::__toString() implemented without string return type",
2791 				ZSTR_VAL(scope->name));
2792 			internal_function->arg_info = (zend_internal_arg_info *) arg_info_toString + 1;
2793 			internal_function->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
2794 			internal_function->num_args = internal_function->required_num_args = 0;
2795 		}
2796 
2797 
2798 		zend_set_function_arg_flags((zend_function*)internal_function);
2799 		if (ptr->flags & ZEND_ACC_ABSTRACT) {
2800 			if (scope) {
2801 				/* This is a class that must be abstract itself. Here we set the check info. */
2802 				scope->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
2803 				if (!(scope->ce_flags & ZEND_ACC_INTERFACE)) {
2804 					/* Since the class is not an interface it needs to be declared as a abstract class. */
2805 					/* Since here we are handling internal functions only we can add the keyword flag. */
2806 					/* This time we set the flag for the keyword 'abstract'. */
2807 					scope->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
2808 				}
2809 			}
2810 			if ((ptr->flags & ZEND_ACC_STATIC) && (!scope || !(scope->ce_flags & ZEND_ACC_INTERFACE))) {
2811 				zend_error(error_type, "Static function %s%s%s() cannot be abstract", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2812 			}
2813 		} else {
2814 			if (scope && (scope->ce_flags & ZEND_ACC_INTERFACE)) {
2815 				zend_error(error_type, "Interface %s cannot contain non abstract method %s()", ZSTR_VAL(scope->name), ptr->fname);
2816 				return FAILURE;
2817 			}
2818 			if (!internal_function->handler) {
2819 				zend_error(error_type, "Method %s%s%s() cannot be a NULL function", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2820 				zend_unregister_functions(functions, count, target_function_table);
2821 				return FAILURE;
2822 			}
2823 		}
2824 		lowercase_name = zend_string_tolower_ex(internal_function->function_name, type == MODULE_PERSISTENT);
2825 		lowercase_name = zend_new_interned_string(lowercase_name);
2826 		reg_function = malloc(sizeof(zend_internal_function));
2827 		memcpy(reg_function, &function, sizeof(zend_internal_function));
2828 		if (zend_hash_add_ptr(target_function_table, lowercase_name, reg_function) == NULL) {
2829 			unload=1;
2830 			free(reg_function);
2831 			zend_string_release(lowercase_name);
2832 			break;
2833 		}
2834 
2835 		/* Get parameter count including variadic parameter. */
2836 		uint32_t num_args = reg_function->common.num_args;
2837 		if (reg_function->common.fn_flags & ZEND_ACC_VARIADIC) {
2838 			num_args++;
2839 		}
2840 
2841 		/* If types of arguments have to be checked */
2842 		if (reg_function->common.arg_info && num_args) {
2843 			uint32_t i;
2844 			for (i = 0; i < num_args; i++) {
2845 				zend_internal_arg_info *arg_info = &reg_function->internal_function.arg_info[i];
2846 				ZEND_ASSERT(arg_info->name && "Parameter must have a name");
2847 				if (ZEND_TYPE_IS_SET(arg_info->type)) {
2848 				    reg_function->common.fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
2849 				}
2850 #if ZEND_DEBUG
2851 				for (uint32_t j = 0; j < i; j++) {
2852 					if (!strcmp(arg_info->name, reg_function->internal_function.arg_info[j].name)) {
2853 						zend_error_noreturn(E_CORE_ERROR,
2854 							"Duplicate parameter name $%s for function %s%s%s()", arg_info->name,
2855 							scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2856 					}
2857 				}
2858 #endif
2859 			}
2860 		}
2861 
2862 		/* Rebuild arginfos if parameter/property types and/or a return type are used */
2863 		if (reg_function->common.arg_info &&
2864 		    (reg_function->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS))) {
2865 			/* convert "const char*" class type names into "zend_string*" */
2866 			uint32_t i;
2867 			zend_arg_info *arg_info = reg_function->common.arg_info - 1;
2868 			zend_arg_info *new_arg_info;
2869 
2870 			/* Treat return type as an extra argument */
2871 			num_args++;
2872 			new_arg_info = malloc(sizeof(zend_arg_info) * num_args);
2873 			memcpy(new_arg_info, arg_info, sizeof(zend_arg_info) * num_args);
2874 			reg_function->common.arg_info = new_arg_info + 1;
2875 			for (i = 0; i < num_args; i++) {
2876 				if (ZEND_TYPE_IS_COMPLEX(new_arg_info[i].type)) {
2877 					ZEND_ASSERT(ZEND_TYPE_HAS_NAME(new_arg_info[i].type)
2878 						&& "Should be stored as simple name");
2879 					const char *class_name = ZEND_TYPE_LITERAL_NAME(new_arg_info[i].type);
2880 
2881 					size_t num_types = 1;
2882 					const char *p = class_name;
2883 					while ((p = strchr(p, '|'))) {
2884 						num_types++;
2885 						p++;
2886 					}
2887 
2888 					if (num_types == 1) {
2889 						/* Simple class type */
2890 						ZEND_TYPE_SET_PTR(new_arg_info[i].type,
2891 							zend_string_init_interned(class_name, strlen(class_name), 1));
2892 					} else {
2893 						/* Union type */
2894 						zend_type_list *list = malloc(ZEND_TYPE_LIST_SIZE(num_types));
2895 						list->num_types = num_types;
2896 						ZEND_TYPE_SET_LIST(new_arg_info[i].type, list);
2897 						ZEND_TYPE_FULL_MASK(new_arg_info[i].type) |= _ZEND_TYPE_UNION_BIT;
2898 
2899 						const char *start = class_name;
2900 						uint32_t j = 0;
2901 						while (true) {
2902 							const char *end = strchr(start, '|');
2903 							zend_string *str = zend_string_init_interned(
2904 								start, end ? end - start : strlen(start), 1);
2905 							list->types[j] = (zend_type) ZEND_TYPE_INIT_CLASS(str, 0, 0);
2906 							if (!end) {
2907 								break;
2908 							}
2909 							start = end + 1;
2910 							j++;
2911 						}
2912 					}
2913 				}
2914 				if (ZEND_TYPE_IS_ITERABLE_FALLBACK(new_arg_info[i].type)) {
2915 					/* Warning generated an extension load warning which is emitted for every test
2916 					zend_error(E_CORE_WARNING, "iterable type is now a compile time alias for array|Traversable,"
2917 						" regenerate the argument info via the php-src gen_stub build script");
2918 					*/
2919 					zend_type legacy_iterable = ZEND_TYPE_INIT_CLASS_CONST_MASK(ZSTR_KNOWN(ZEND_STR_TRAVERSABLE),
2920 						(new_arg_info[i].type.type_mask|MAY_BE_ARRAY));
2921 					new_arg_info[i].type = legacy_iterable;
2922 				}
2923 			}
2924 		}
2925 
2926 		if (scope) {
2927 			zend_check_magic_method_implementation(
2928 				scope, reg_function, lowercase_name, E_CORE_ERROR);
2929 			zend_add_magic_method(scope, reg_function, lowercase_name);
2930 		}
2931 		ptr++;
2932 		count++;
2933 		zend_string_release(lowercase_name);
2934 	}
2935 	if (unload) { /* before unloading, display all remaining bad function in the module */
2936 		while (ptr->fname) {
2937 			fname_len = strlen(ptr->fname);
2938 			lowercase_name = zend_string_alloc(fname_len, 0);
2939 			zend_str_tolower_copy(ZSTR_VAL(lowercase_name), ptr->fname, fname_len);
2940 			if (zend_hash_exists(target_function_table, lowercase_name)) {
2941 				zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? ZSTR_VAL(scope->name) : "", scope ? "::" : "", ptr->fname);
2942 			}
2943 			zend_string_efree(lowercase_name);
2944 			ptr++;
2945 		}
2946 		zend_unregister_functions(functions, count, target_function_table);
2947 		return FAILURE;
2948 	}
2949 	return SUCCESS;
2950 }
2951 /* }}} */
2952 
2953 /* count=-1 means erase all functions, otherwise,
2954  * erase the first count functions
2955  */
zend_unregister_functions(const zend_function_entry * functions,int count,HashTable * function_table)2956 ZEND_API void zend_unregister_functions(const zend_function_entry *functions, int count, HashTable *function_table) /* {{{ */
2957 {
2958 	const zend_function_entry *ptr = functions;
2959 	int i=0;
2960 	HashTable *target_function_table = function_table;
2961 	zend_string *lowercase_name;
2962 	size_t fname_len;
2963 
2964 	if (!target_function_table) {
2965 		target_function_table = CG(function_table);
2966 	}
2967 	while (ptr->fname) {
2968 		if (count!=-1 && i>=count) {
2969 			break;
2970 		}
2971 		fname_len = strlen(ptr->fname);
2972 		lowercase_name = zend_string_alloc(fname_len, 0);
2973 		zend_str_tolower_copy(ZSTR_VAL(lowercase_name), ptr->fname, fname_len);
2974 		zend_hash_del(target_function_table, lowercase_name);
2975 		zend_string_efree(lowercase_name);
2976 		ptr++;
2977 		i++;
2978 	}
2979 }
2980 /* }}} */
2981 
zend_startup_module(zend_module_entry * module)2982 ZEND_API zend_result zend_startup_module(zend_module_entry *module) /* {{{ */
2983 {
2984 	if ((module = zend_register_internal_module(module)) != NULL && zend_startup_module_ex(module) == SUCCESS) {
2985 		return SUCCESS;
2986 	}
2987 	return FAILURE;
2988 }
2989 /* }}} */
2990 
zend_get_module_started(const char * module_name)2991 ZEND_API zend_result zend_get_module_started(const char *module_name) /* {{{ */
2992 {
2993 	zend_module_entry *module;
2994 
2995 	module = zend_hash_str_find_ptr(&module_registry, module_name, strlen(module_name));
2996 	return (module && module->module_started) ? SUCCESS : FAILURE;
2997 }
2998 /* }}} */
2999 
clean_module_class(zval * el,void * arg)3000 static int clean_module_class(zval *el, void *arg) /* {{{ */
3001 {
3002 	zend_class_entry *ce = (zend_class_entry *)Z_PTR_P(el);
3003 	int module_number = *(int *)arg;
3004 	if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module->module_number == module_number) {
3005 		return ZEND_HASH_APPLY_REMOVE;
3006 	} else {
3007 		return ZEND_HASH_APPLY_KEEP;
3008 	}
3009 }
3010 /* }}} */
3011 
clean_module_classes(int module_number)3012 static void clean_module_classes(int module_number) /* {{{ */
3013 {
3014 	zend_hash_apply_with_argument(EG(class_table), clean_module_class, (void *) &module_number);
3015 }
3016 /* }}} */
3017 
clean_module_function(zval * el,void * arg)3018 static int clean_module_function(zval *el, void *arg) /* {{{ */
3019 {
3020 	zend_function *fe = (zend_function *) Z_PTR_P(el);
3021 	zend_module_entry *module = (zend_module_entry *) arg;
3022 	if (fe->common.type == ZEND_INTERNAL_FUNCTION && fe->internal_function.module == module) {
3023 		return ZEND_HASH_APPLY_REMOVE;
3024 	} else {
3025 		return ZEND_HASH_APPLY_KEEP;
3026 	}
3027 }
3028 /* }}} */
3029 
clean_module_functions(zend_module_entry * module)3030 static void clean_module_functions(zend_module_entry *module) /* {{{ */
3031 {
3032 	zend_hash_apply_with_argument(CG(function_table), clean_module_function, module);
3033 }
3034 /* }}} */
3035 
module_destructor(zend_module_entry * module)3036 void module_destructor(zend_module_entry *module) /* {{{ */
3037 {
3038 #if ZEND_RC_DEBUG
3039 	bool orig_rc_debug = zend_rc_debug;
3040 #endif
3041 
3042 	if (module->type == MODULE_TEMPORARY) {
3043 #if ZEND_RC_DEBUG
3044 		/* FIXME: Loading extensions during the request breaks some invariants.
3045 		 * In particular, it will create persistent interned strings, which is
3046 		 * not allowed at this stage. */
3047 		zend_rc_debug = false;
3048 #endif
3049 		zend_clean_module_rsrc_dtors(module->module_number);
3050 		clean_module_constants(module->module_number);
3051 		clean_module_classes(module->module_number);
3052 	}
3053 
3054 	if (module->module_started && module->module_shutdown_func) {
3055 #if 0
3056 		zend_printf("%s: Module shutdown\n", module->name);
3057 #endif
3058 		module->module_shutdown_func(module->type, module->module_number);
3059 	}
3060 
3061 	if (module->module_started
3062 	 && !module->module_shutdown_func
3063 	 && module->type == MODULE_TEMPORARY) {
3064 		zend_unregister_ini_entries_ex(module->module_number, module->type);
3065 	}
3066 
3067 	/* Deinitialize module globals */
3068 	if (module->globals_size) {
3069 #ifdef ZTS
3070 		if (*module->globals_id_ptr) {
3071 			ts_free_id(*module->globals_id_ptr);
3072 		}
3073 #else
3074 		if (module->globals_dtor) {
3075 			module->globals_dtor(module->globals_ptr);
3076 		}
3077 #endif
3078 	}
3079 
3080 	module->module_started=0;
3081 	if (module->type == MODULE_TEMPORARY && module->functions) {
3082 		zend_unregister_functions(module->functions, -1, NULL);
3083 		/* Clean functions registered separately from module->functions */
3084 		clean_module_functions(module);
3085 	}
3086 
3087 #if ZEND_RC_DEBUG
3088 	zend_rc_debug = orig_rc_debug;
3089 #endif
3090 }
3091 /* }}} */
3092 
module_registry_unload(const zend_module_entry * module)3093 void module_registry_unload(const zend_module_entry *module)
3094 {
3095 #if HAVE_LIBDL
3096 	if (!getenv("ZEND_DONT_UNLOAD_MODULES")) {
3097 		DL_UNLOAD(module->handle);
3098 	}
3099 #else
3100 	ZEND_IGNORE_VALUE(module);
3101 #endif
3102 }
3103 
zend_activate_modules(void)3104 ZEND_API void zend_activate_modules(void) /* {{{ */
3105 {
3106 	zend_module_entry **p = module_request_startup_handlers;
3107 
3108 	while (*p) {
3109 		zend_module_entry *module = *p;
3110 
3111 		if (module->request_startup_func(module->type, module->module_number)==FAILURE) {
3112 			zend_error(E_WARNING, "request_startup() for %s module failed", module->name);
3113 			exit(1);
3114 		}
3115 		p++;
3116 	}
3117 }
3118 /* }}} */
3119 
zend_deactivate_modules(void)3120 ZEND_API void zend_deactivate_modules(void) /* {{{ */
3121 {
3122 	EG(current_execute_data) = NULL; /* we're no longer executing anything */
3123 
3124 	if (EG(full_tables_cleanup)) {
3125 		zend_module_entry *module;
3126 
3127 		ZEND_HASH_MAP_REVERSE_FOREACH_PTR(&module_registry, module) {
3128 			if (module->request_shutdown_func) {
3129 				zend_try {
3130 					module->request_shutdown_func(module->type, module->module_number);
3131 				} zend_end_try();
3132 			}
3133 		} ZEND_HASH_FOREACH_END();
3134 	} else {
3135 		zend_module_entry **p = module_request_shutdown_handlers;
3136 
3137 		while (*p) {
3138 			zend_module_entry *module = *p;
3139 			zend_try {
3140 				module->request_shutdown_func(module->type, module->module_number);
3141 			} zend_end_try();
3142 			p++;
3143 		}
3144 	}
3145 }
3146 /* }}} */
3147 
zend_unload_modules(void)3148 void zend_unload_modules(void) /* {{{ */
3149 {
3150 	zend_module_entry **modules = modules_dl_loaded;
3151 	while (*modules) {
3152 		module_registry_unload(*modules);
3153 		modules++;
3154 	}
3155 	free(modules_dl_loaded);
3156 	modules_dl_loaded = NULL;
3157 }
3158 /* }}} */
3159 
zend_post_deactivate_modules(void)3160 ZEND_API void zend_post_deactivate_modules(void) /* {{{ */
3161 {
3162 	if (EG(full_tables_cleanup)) {
3163 		zend_module_entry *module;
3164 		zval *zv;
3165 		zend_string *key;
3166 
3167 		ZEND_HASH_MAP_FOREACH_PTR(&module_registry, module) {
3168 			if (module->post_deactivate_func) {
3169 				module->post_deactivate_func();
3170 			}
3171 		} ZEND_HASH_FOREACH_END();
3172 		ZEND_HASH_MAP_REVERSE_FOREACH_STR_KEY_VAL(&module_registry, key, zv) {
3173 			module = Z_PTR_P(zv);
3174 			if (module->type != MODULE_TEMPORARY) {
3175 				break;
3176 			}
3177 			module_destructor(module);
3178 			if (module->handle) {
3179 				module_registry_unload(module);
3180 			}
3181 			zend_string_release_ex(key, 0);
3182 		} ZEND_HASH_MAP_FOREACH_END_DEL();
3183 	} else {
3184 		zend_module_entry **p = module_post_deactivate_handlers;
3185 
3186 		while (*p) {
3187 			zend_module_entry *module = *p;
3188 
3189 			module->post_deactivate_func();
3190 			p++;
3191 		}
3192 	}
3193 }
3194 /* }}} */
3195 
3196 /* return the next free module number */
zend_next_free_module(void)3197 ZEND_API int zend_next_free_module(void) /* {{{ */
3198 {
3199 	return zend_hash_num_elements(&module_registry) + 1;
3200 }
3201 /* }}} */
3202 
do_register_internal_class(zend_class_entry * orig_class_entry,uint32_t ce_flags)3203 static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, uint32_t ce_flags) /* {{{ */
3204 {
3205 	zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
3206 	zend_string *lowercase_name;
3207 	*class_entry = *orig_class_entry;
3208 
3209 	class_entry->type = ZEND_INTERNAL_CLASS;
3210 	zend_initialize_class_data(class_entry, 0);
3211 	zend_alloc_ce_cache(class_entry->name);
3212 	class_entry->ce_flags = orig_class_entry->ce_flags | ce_flags | ZEND_ACC_CONSTANTS_UPDATED | ZEND_ACC_LINKED | ZEND_ACC_RESOLVED_PARENT | ZEND_ACC_RESOLVED_INTERFACES;
3213 	class_entry->info.internal.module = EG(current_module);
3214 
3215 	if (class_entry->info.internal.builtin_functions) {
3216 		zend_register_functions(class_entry, class_entry->info.internal.builtin_functions, &class_entry->function_table, EG(current_module)->type);
3217 	}
3218 
3219 	lowercase_name = zend_string_tolower_ex(orig_class_entry->name, EG(current_module)->type == MODULE_PERSISTENT);
3220 	lowercase_name = zend_new_interned_string(lowercase_name);
3221 	zend_hash_update_ptr(CG(class_table), lowercase_name, class_entry);
3222 	zend_string_release_ex(lowercase_name, 1);
3223 
3224 	if (class_entry->__tostring && !zend_string_equals_literal(class_entry->name, "Stringable")
3225 			&& !(class_entry->ce_flags & ZEND_ACC_TRAIT)) {
3226 		ZEND_ASSERT(zend_ce_stringable
3227 			&& "Should be registered before first class using __toString()");
3228 		zend_do_implement_interface(class_entry, zend_ce_stringable);
3229 	}
3230 	return class_entry;
3231 }
3232 /* }}} */
3233 
3234 /* If parent_ce is not NULL then it inherits from parent_ce
3235  * If parent_ce is NULL and parent_name isn't then it looks for the parent and inherits from it
3236  * If both parent_ce and parent_name are NULL it does a regular class registration
3237  * If parent_name is specified but not found NULL is returned
3238  */
zend_register_internal_class_ex(zend_class_entry * class_entry,zend_class_entry * parent_ce)3239 ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce) /* {{{ */
3240 {
3241 	zend_class_entry *register_class;
3242 
3243 	register_class = zend_register_internal_class(class_entry);
3244 
3245 	if (parent_ce) {
3246 		zend_do_inheritance(register_class, parent_ce);
3247 		zend_build_properties_info_table(register_class);
3248 	}
3249 
3250 	return register_class;
3251 }
3252 /* }}} */
3253 
zend_class_implements(zend_class_entry * class_entry,int num_interfaces,...)3254 ZEND_API void zend_class_implements(zend_class_entry *class_entry, int num_interfaces, ...) /* {{{ */
3255 {
3256 	zend_class_entry *interface_entry;
3257 	va_list interface_list;
3258 	va_start(interface_list, num_interfaces);
3259 
3260 	while (num_interfaces--) {
3261 		interface_entry = va_arg(interface_list, zend_class_entry *);
3262 		if (interface_entry == zend_ce_stringable
3263 				&& zend_class_implements_interface(class_entry, zend_ce_stringable)) {
3264 			/* Stringable is implemented automatically,
3265 			 * silently ignore an explicit implementation. */
3266 			continue;
3267 		}
3268 
3269 		zend_do_implement_interface(class_entry, interface_entry);
3270 	}
3271 
3272 	va_end(interface_list);
3273 }
3274 /* }}} */
3275 
3276 /* A class that contains at least one abstract method automatically becomes an abstract class.
3277  */
zend_register_internal_class(zend_class_entry * orig_class_entry)3278 ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry) /* {{{ */
3279 {
3280 	return do_register_internal_class(orig_class_entry, 0);
3281 }
3282 /* }}} */
3283 
zend_register_internal_interface(zend_class_entry * orig_class_entry)3284 ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry) /* {{{ */
3285 {
3286 	return do_register_internal_class(orig_class_entry, ZEND_ACC_INTERFACE);
3287 }
3288 /* }}} */
3289 
zend_register_class_alias_ex(const char * name,size_t name_len,zend_class_entry * ce,bool persistent)3290 ZEND_API zend_result zend_register_class_alias_ex(const char *name, size_t name_len, zend_class_entry *ce, bool persistent) /* {{{ */
3291 {
3292 	zend_string *lcname;
3293 	zval zv, *ret;
3294 
3295 	/* TODO: Move this out of here in 7.4. */
3296 	if (persistent && EG(current_module) && EG(current_module)->type == MODULE_TEMPORARY) {
3297 		persistent = 0;
3298 	}
3299 
3300 	if (name[0] == '\\') {
3301 		lcname = zend_string_alloc(name_len-1, persistent);
3302 		zend_str_tolower_copy(ZSTR_VAL(lcname), name+1, name_len-1);
3303 	} else {
3304 		lcname = zend_string_alloc(name_len, persistent);
3305 		zend_str_tolower_copy(ZSTR_VAL(lcname), name, name_len);
3306 	}
3307 
3308 	zend_assert_valid_class_name(lcname);
3309 
3310 	lcname = zend_new_interned_string(lcname);
3311 
3312 	ZVAL_ALIAS_PTR(&zv, ce);
3313 	ret = zend_hash_add(CG(class_table), lcname, &zv);
3314 	zend_string_release_ex(lcname, 0);
3315 	if (ret) {
3316 		if (!(ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
3317 			ce->refcount++;
3318 		}
3319 		// avoid notifying at MINIT time
3320 		if (ce->type == ZEND_USER_CLASS) {
3321 			zend_observer_class_linked_notify(ce, lcname);
3322 		}
3323 		return SUCCESS;
3324 	}
3325 	return FAILURE;
3326 }
3327 /* }}} */
3328 
3329 // TODO num_symbol_tables as unsigned int?
zend_set_hash_symbol(zval * symbol,const char * name,size_t name_length,bool is_ref,int num_symbol_tables,...)3330 ZEND_API zend_result zend_set_hash_symbol(zval *symbol, const char *name, size_t name_length, bool is_ref, int num_symbol_tables, ...) /* {{{ */
3331 {
3332 	HashTable *symbol_table;
3333 	va_list symbol_table_list;
3334 
3335 	if (num_symbol_tables <= 0) return FAILURE;
3336 
3337 	if (is_ref) {
3338 		ZVAL_MAKE_REF(symbol);
3339 	}
3340 
3341 	va_start(symbol_table_list, num_symbol_tables);
3342 	while (num_symbol_tables-- > 0) {
3343 		symbol_table = va_arg(symbol_table_list, HashTable *);
3344 		zend_hash_str_update(symbol_table, name, name_length, symbol);
3345 		Z_TRY_ADDREF_P(symbol);
3346 	}
3347 	va_end(symbol_table_list);
3348 	return SUCCESS;
3349 }
3350 /* }}} */
3351 
3352 /* Disabled functions support */
3353 
zend_disable_function(const char * function_name,size_t function_name_length)3354 static void zend_disable_function(const char *function_name, size_t function_name_length)
3355 {
3356 	zend_hash_str_del(CG(function_table), function_name, function_name_length);
3357 }
3358 
zend_disable_functions(const char * function_list)3359 ZEND_API void zend_disable_functions(const char *function_list) /* {{{ */
3360 {
3361 	if (!function_list || !*function_list) {
3362 		return;
3363 	}
3364 
3365 	const char *s = NULL, *e = function_list;
3366 	while (*e) {
3367 		switch (*e) {
3368 			case ' ':
3369 			case ',':
3370 				if (s) {
3371 					zend_disable_function(s, e - s);
3372 					s = NULL;
3373 				}
3374 				break;
3375 			default:
3376 				if (!s) {
3377 					s = e;
3378 				}
3379 				break;
3380 		}
3381 		e++;
3382 	}
3383 	if (s) {
3384 		zend_disable_function(s, e - s);
3385 	}
3386 
3387 	/* Rehash the function table after deleting functions. This ensures that all internal
3388 	 * functions are contiguous, which means we don't need to perform full table cleanup
3389 	 * on shutdown. */
3390 	zend_hash_rehash(CG(function_table));
3391 }
3392 /* }}} */
3393 
3394 #ifdef ZEND_WIN32
3395 #pragma optimize("", off)
3396 #endif
display_disabled_class(zend_class_entry * class_type)3397 static ZEND_COLD zend_object *display_disabled_class(zend_class_entry *class_type) /* {{{ */
3398 {
3399 	zend_object *intern;
3400 
3401 	intern = zend_objects_new(class_type);
3402 
3403 	/* Initialize default properties */
3404 	if (EXPECTED(class_type->default_properties_count != 0)) {
3405 		zval *p = intern->properties_table;
3406 		zval *end = p + class_type->default_properties_count;
3407 		do {
3408 			ZVAL_UNDEF(p);
3409 			p++;
3410 		} while (p != end);
3411 	}
3412 
3413 	zend_error(E_WARNING, "%s() has been disabled for security reasons", ZSTR_VAL(class_type->name));
3414 	return intern;
3415 }
3416 #ifdef ZEND_WIN32
3417 #pragma optimize("", on)
3418 #endif
3419 /* }}} */
3420 
3421 static const zend_function_entry disabled_class_new[] = {
3422 	ZEND_FE_END
3423 };
3424 
zend_disable_class(const char * class_name,size_t class_name_length)3425 ZEND_API zend_result zend_disable_class(const char *class_name, size_t class_name_length) /* {{{ */
3426 {
3427 	zend_class_entry *disabled_class;
3428 	zend_string *key;
3429 	zend_function *fn;
3430 	zend_property_info *prop;
3431 
3432 	key = zend_string_alloc(class_name_length, 0);
3433 	zend_str_tolower_copy(ZSTR_VAL(key), class_name, class_name_length);
3434 	disabled_class = zend_hash_find_ptr(CG(class_table), key);
3435 	zend_string_release_ex(key, 0);
3436 	if (!disabled_class) {
3437 		return FAILURE;
3438 	}
3439 
3440 	/* Will be reset by INIT_CLASS_ENTRY. */
3441 	free(disabled_class->interfaces);
3442 
3443 	INIT_CLASS_ENTRY_INIT_METHODS((*disabled_class), disabled_class_new);
3444 	disabled_class->create_object = display_disabled_class;
3445 
3446 	ZEND_HASH_MAP_FOREACH_PTR(&disabled_class->function_table, fn) {
3447 		if ((fn->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS)) &&
3448 			fn->common.scope == disabled_class) {
3449 			zend_free_internal_arg_info(&fn->internal_function);
3450 		}
3451 	} ZEND_HASH_FOREACH_END();
3452 	zend_hash_clean(&disabled_class->function_table);
3453 	ZEND_HASH_MAP_FOREACH_PTR(&disabled_class->properties_info, prop) {
3454 		if (prop->ce == disabled_class) {
3455 			zend_string_release(prop->name);
3456 			zend_type_release(prop->type, /* persistent */ 1);
3457 			free(prop);
3458 		}
3459 	} ZEND_HASH_FOREACH_END();
3460 	zend_hash_clean(&disabled_class->properties_info);
3461 	return SUCCESS;
3462 }
3463 /* }}} */
3464 
get_scope(zend_execute_data * frame)3465 static zend_always_inline zend_class_entry *get_scope(zend_execute_data *frame)
3466 {
3467 	return frame && frame->func ? frame->func->common.scope : NULL;
3468 }
3469 
zend_is_callable_check_class(zend_string * name,zend_class_entry * scope,zend_execute_data * frame,zend_fcall_info_cache * fcc,bool * strict_class,char ** error,bool suppress_deprecation)3470 static bool zend_is_callable_check_class(zend_string *name, zend_class_entry *scope, zend_execute_data *frame, zend_fcall_info_cache *fcc, bool *strict_class, char **error, bool suppress_deprecation) /* {{{ */
3471 {
3472 	bool ret = 0;
3473 	zend_class_entry *ce;
3474 	size_t name_len = ZSTR_LEN(name);
3475 	zend_string *lcname;
3476 	ALLOCA_FLAG(use_heap);
3477 
3478 	ZSTR_ALLOCA_ALLOC(lcname, name_len, use_heap);
3479 	zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(name), name_len);
3480 
3481 	*strict_class = 0;
3482 	if (zend_string_equals_literal(lcname, "self")) {
3483 		if (!scope) {
3484 			if (error) *error = estrdup("cannot access \"self\" when no class scope is active");
3485 		} else {
3486 			if (!suppress_deprecation) {
3487 				zend_error(E_DEPRECATED, "Use of \"self\" in callables is deprecated");
3488 			}
3489 			fcc->called_scope = zend_get_called_scope(frame);
3490 			if (!fcc->called_scope || !instanceof_function(fcc->called_scope, scope)) {
3491 				fcc->called_scope = scope;
3492 			}
3493 			fcc->calling_scope = scope;
3494 			if (!fcc->object) {
3495 				fcc->object = zend_get_this_object(frame);
3496 			}
3497 			ret = 1;
3498 		}
3499 	} else if (zend_string_equals_literal(lcname, "parent")) {
3500 		if (!scope) {
3501 			if (error) *error = estrdup("cannot access \"parent\" when no class scope is active");
3502 		} else if (!scope->parent) {
3503 			if (error) *error = estrdup("cannot access \"parent\" when current class scope has no parent");
3504 		} else {
3505 			if (!suppress_deprecation) {
3506 				zend_error(E_DEPRECATED, "Use of \"parent\" in callables is deprecated");
3507 			}
3508 			fcc->called_scope = zend_get_called_scope(frame);
3509 			if (!fcc->called_scope || !instanceof_function(fcc->called_scope, scope->parent)) {
3510 				fcc->called_scope = scope->parent;
3511 			}
3512 			fcc->calling_scope = scope->parent;
3513 			if (!fcc->object) {
3514 				fcc->object = zend_get_this_object(frame);
3515 			}
3516 			*strict_class = 1;
3517 			ret = 1;
3518 		}
3519 	} else if (zend_string_equals_literal(lcname, "static")) {
3520 		zend_class_entry *called_scope = zend_get_called_scope(frame);
3521 
3522 		if (!called_scope) {
3523 			if (error) *error = estrdup("cannot access \"static\" when no class scope is active");
3524 		} else {
3525 			if (!suppress_deprecation) {
3526 				zend_error(E_DEPRECATED, "Use of \"static\" in callables is deprecated");
3527 			}
3528 			fcc->called_scope = called_scope;
3529 			fcc->calling_scope = called_scope;
3530 			if (!fcc->object) {
3531 				fcc->object = zend_get_this_object(frame);
3532 			}
3533 			*strict_class = 1;
3534 			ret = 1;
3535 		}
3536 	} else if ((ce = zend_lookup_class(name)) != NULL) {
3537 		zend_class_entry *scope = get_scope(frame);
3538 		fcc->calling_scope = ce;
3539 		if (scope && !fcc->object) {
3540 			zend_object *object = zend_get_this_object(frame);
3541 
3542 			if (object &&
3543 			    instanceof_function(object->ce, scope) &&
3544 			    instanceof_function(scope, ce)) {
3545 				fcc->object = object;
3546 				fcc->called_scope = object->ce;
3547 			} else {
3548 				fcc->called_scope = ce;
3549 			}
3550 		} else {
3551 			fcc->called_scope = fcc->object ? fcc->object->ce : ce;
3552 		}
3553 		*strict_class = 1;
3554 		ret = 1;
3555 	} else {
3556 		if (error) zend_spprintf(error, 0, "class \"%.*s\" not found", (int)name_len, ZSTR_VAL(name));
3557 	}
3558 	ZSTR_ALLOCA_FREE(lcname, use_heap);
3559 	return ret;
3560 }
3561 /* }}} */
3562 
zend_release_fcall_info_cache(zend_fcall_info_cache * fcc)3563 ZEND_API void zend_release_fcall_info_cache(zend_fcall_info_cache *fcc) {
3564 	if (fcc->function_handler &&
3565 		(fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
3566 		if (fcc->function_handler->common.function_name) {
3567 			zend_string_release_ex(fcc->function_handler->common.function_name, 0);
3568 		}
3569 		zend_free_trampoline(fcc->function_handler);
3570 		fcc->function_handler = NULL;
3571 	}
3572 }
3573 
zend_is_callable_check_func(zval * callable,zend_execute_data * frame,zend_fcall_info_cache * fcc,bool strict_class,char ** error,bool suppress_deprecation)3574 static zend_always_inline bool zend_is_callable_check_func(zval *callable, zend_execute_data *frame, zend_fcall_info_cache *fcc, bool strict_class, char **error, bool suppress_deprecation) /* {{{ */
3575 {
3576 	zend_class_entry *ce_org = fcc->calling_scope;
3577 	bool retval = 0;
3578 	zend_string *mname, *cname;
3579 	zend_string *lmname;
3580 	const char *colon;
3581 	size_t clen;
3582 	HashTable *ftable;
3583 	int call_via_handler = 0;
3584 	zend_class_entry *scope;
3585 	zval *zv;
3586 	ALLOCA_FLAG(use_heap)
3587 
3588 	fcc->calling_scope = NULL;
3589 
3590 	if (!ce_org) {
3591 		zend_function *func;
3592 		zend_string *lmname;
3593 
3594 		/* Check if function with given name exists.
3595 		 * This may be a compound name that includes namespace name */
3596 		if (UNEXPECTED(Z_STRVAL_P(callable)[0] == '\\')) {
3597 			/* Skip leading \ */
3598 			ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable) - 1, use_heap);
3599 			zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable) + 1, Z_STRLEN_P(callable) - 1);
3600 			func = zend_fetch_function(lmname);
3601 			ZSTR_ALLOCA_FREE(lmname, use_heap);
3602 		} else {
3603 			lmname = Z_STR_P(callable);
3604 			func = zend_fetch_function(lmname);
3605 			if (!func) {
3606 				ZSTR_ALLOCA_ALLOC(lmname, Z_STRLEN_P(callable), use_heap);
3607 				zend_str_tolower_copy(ZSTR_VAL(lmname), Z_STRVAL_P(callable), Z_STRLEN_P(callable));
3608 				func = zend_fetch_function(lmname);
3609 				ZSTR_ALLOCA_FREE(lmname, use_heap);
3610 			}
3611 		}
3612 		if (EXPECTED(func != NULL)) {
3613 			fcc->function_handler = func;
3614 			return 1;
3615 		}
3616 	}
3617 
3618 	/* Split name into class/namespace and method/function names */
3619 	if ((colon = zend_memrchr(Z_STRVAL_P(callable), ':', Z_STRLEN_P(callable))) != NULL &&
3620 		colon > Z_STRVAL_P(callable) &&
3621 		*(colon-1) == ':'
3622 	) {
3623 		size_t mlen;
3624 
3625 		colon--;
3626 		clen = colon - Z_STRVAL_P(callable);
3627 		mlen = Z_STRLEN_P(callable) - clen - 2;
3628 
3629 		if (colon == Z_STRVAL_P(callable)) {
3630 			if (error) *error = estrdup("invalid function name");
3631 			return 0;
3632 		}
3633 
3634 		/* This is a compound name.
3635 		 * Try to fetch class and then find static method. */
3636 		if (ce_org) {
3637 			scope = ce_org;
3638 		} else {
3639 			scope = get_scope(frame);
3640 		}
3641 
3642 		cname = zend_string_init_interned(Z_STRVAL_P(callable), clen, 0);
3643 		if (ZSTR_HAS_CE_CACHE(cname) && ZSTR_GET_CE_CACHE(cname)) {
3644 			fcc->calling_scope = ZSTR_GET_CE_CACHE(cname);
3645 			if (scope && !fcc->object) {
3646 				zend_object *object = zend_get_this_object(frame);
3647 
3648 				if (object &&
3649 				    instanceof_function(object->ce, scope) &&
3650 				    instanceof_function(scope, fcc->calling_scope)) {
3651 					fcc->object = object;
3652 					fcc->called_scope = object->ce;
3653 				} else {
3654 					fcc->called_scope = fcc->calling_scope;
3655 				}
3656 			} else {
3657 				fcc->called_scope = fcc->object ? fcc->object->ce : fcc->calling_scope;
3658 			}
3659 			strict_class = 1;
3660 		} else if (!zend_is_callable_check_class(cname, scope, frame, fcc, &strict_class, error, suppress_deprecation || ce_org != NULL)) {
3661 			zend_string_release_ex(cname, 0);
3662 			return 0;
3663 		}
3664 		zend_string_release_ex(cname, 0);
3665 
3666 		ftable = &fcc->calling_scope->function_table;
3667 		if (ce_org && !instanceof_function(ce_org, fcc->calling_scope)) {
3668 			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));
3669 			return 0;
3670 		}
3671 		if (ce_org && !suppress_deprecation) {
3672 			zend_error(E_DEPRECATED,
3673 				"Callables of the form [\"%s\", \"%s\"] are deprecated",
3674 				ZSTR_VAL(ce_org->name), Z_STRVAL_P(callable));
3675 		}
3676 		mname = zend_string_init(Z_STRVAL_P(callable) + clen + 2, mlen, 0);
3677 	} else if (ce_org) {
3678 		/* Try to fetch find static method of given class. */
3679 		mname = Z_STR_P(callable);
3680 		zend_string_addref(mname);
3681 		ftable = &ce_org->function_table;
3682 		fcc->calling_scope = ce_org;
3683 	} else {
3684 		/* We already checked for plain function before. */
3685 		if (error) {
3686 			zend_spprintf(error, 0, "function \"%s\" not found or invalid function name", Z_STRVAL_P(callable));
3687 		}
3688 		return 0;
3689 	}
3690 
3691 	lmname = zend_string_tolower(mname);
3692 	if (strict_class &&
3693 	    fcc->calling_scope &&
3694 		zend_string_equals_literal(lmname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
3695 		fcc->function_handler = fcc->calling_scope->constructor;
3696 		if (fcc->function_handler) {
3697 			retval = 1;
3698 		}
3699 	} else if ((zv = zend_hash_find(ftable, lmname)) != NULL) {
3700 		fcc->function_handler = Z_PTR_P(zv);
3701 		retval = 1;
3702 		if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) &&
3703 		    !strict_class) {
3704 			scope = get_scope(frame);
3705 			if (scope &&
3706 			    instanceof_function(fcc->function_handler->common.scope, scope)) {
3707 
3708 				zv = zend_hash_find(&scope->function_table, lmname);
3709 				if (zv != NULL) {
3710 					zend_function *priv_fbc = Z_PTR_P(zv);
3711 
3712 					if ((priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE)
3713 					 && priv_fbc->common.scope == scope) {
3714 						fcc->function_handler = priv_fbc;
3715 					}
3716 				}
3717 			}
3718 		}
3719 		if (!(fcc->function_handler->common.fn_flags & ZEND_ACC_PUBLIC) &&
3720 		    (fcc->calling_scope &&
3721 		     ((fcc->object && fcc->calling_scope->__call) ||
3722 		      (!fcc->object && fcc->calling_scope->__callstatic)))) {
3723 			scope = get_scope(frame);
3724 			if (fcc->function_handler->common.scope != scope) {
3725 				if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PRIVATE)
3726 				 || !zend_check_protected(zend_get_function_root_class(fcc->function_handler), scope)) {
3727 					retval = 0;
3728 					fcc->function_handler = NULL;
3729 					goto get_function_via_handler;
3730 				}
3731 			}
3732 		}
3733 	} else {
3734 get_function_via_handler:
3735 		if (fcc->object && fcc->calling_scope == ce_org) {
3736 			if (strict_class && ce_org->__call) {
3737 				fcc->function_handler = zend_get_call_trampoline_func(ce_org, mname, 0);
3738 				call_via_handler = 1;
3739 				retval = 1;
3740 			} else {
3741 				fcc->function_handler = fcc->object->handlers->get_method(&fcc->object, mname, NULL);
3742 				if (fcc->function_handler) {
3743 					if (strict_class &&
3744 					    (!fcc->function_handler->common.scope ||
3745 					     !instanceof_function(ce_org, fcc->function_handler->common.scope))) {
3746 						zend_release_fcall_info_cache(fcc);
3747 					} else {
3748 						retval = 1;
3749 						call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
3750 					}
3751 				}
3752 			}
3753 		} else if (fcc->calling_scope) {
3754 			if (fcc->calling_scope->get_static_method) {
3755 				fcc->function_handler = fcc->calling_scope->get_static_method(fcc->calling_scope, mname);
3756 			} else {
3757 				fcc->function_handler = zend_std_get_static_method(fcc->calling_scope, mname, NULL);
3758 			}
3759 			if (fcc->function_handler) {
3760 				retval = 1;
3761 				call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
3762 				if (call_via_handler && !fcc->object) {
3763 					zend_object *object = zend_get_this_object(frame);
3764 					if (object &&
3765 					    instanceof_function(object->ce, fcc->calling_scope)) {
3766 						fcc->object = object;
3767 					}
3768 				}
3769 			}
3770 		}
3771 	}
3772 
3773 	if (retval) {
3774 		if (fcc->calling_scope && !call_via_handler) {
3775 			if (fcc->function_handler->common.fn_flags & ZEND_ACC_ABSTRACT) {
3776 				retval = 0;
3777 				if (error) {
3778 					zend_spprintf(error, 0, "cannot call abstract method %s::%s()", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
3779 				}
3780 			} else if (!fcc->object && !(fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) {
3781 				retval = 0;
3782 				if (error) {
3783 					zend_spprintf(error, 0, "non-static method %s::%s() cannot be called statically", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
3784 				}
3785 			}
3786 			if (retval
3787 			 && !(fcc->function_handler->common.fn_flags & ZEND_ACC_PUBLIC)) {
3788 				scope = get_scope(frame);
3789 				if (fcc->function_handler->common.scope != scope) {
3790 					if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PRIVATE)
3791 					 || (!zend_check_protected(zend_get_function_root_class(fcc->function_handler), scope))) {
3792 						if (error) {
3793 							if (*error) {
3794 								efree(*error);
3795 							}
3796 							zend_spprintf(error, 0, "cannot access %s method %s::%s()", zend_visibility_string(fcc->function_handler->common.fn_flags), ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(fcc->function_handler->common.function_name));
3797 						}
3798 						retval = 0;
3799 					}
3800 				}
3801 			}
3802 		}
3803 	} else if (error) {
3804 		if (fcc->calling_scope) {
3805 			if (error) zend_spprintf(error, 0, "class %s does not have a method \"%s\"", ZSTR_VAL(fcc->calling_scope->name), ZSTR_VAL(mname));
3806 		} else {
3807 			if (error) zend_spprintf(error, 0, "function %s() does not exist", ZSTR_VAL(mname));
3808 		}
3809 	}
3810 	zend_string_release_ex(lmname, 0);
3811 	zend_string_release_ex(mname, 0);
3812 
3813 	if (fcc->object) {
3814 		fcc->called_scope = fcc->object->ce;
3815 		if (fcc->function_handler
3816 		 && (fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) {
3817 			fcc->object = NULL;
3818 		}
3819 	}
3820 	return retval;
3821 }
3822 /* }}} */
3823 
zend_get_callable_name_ex(zval * callable,zend_object * object)3824 ZEND_API zend_string *zend_get_callable_name_ex(zval *callable, zend_object *object) /* {{{ */
3825 {
3826 try_again:
3827 	switch (Z_TYPE_P(callable)) {
3828 		case IS_STRING:
3829 			if (object) {
3830 				return zend_create_member_string(object->ce->name, Z_STR_P(callable));
3831 			}
3832 			return zend_string_copy(Z_STR_P(callable));
3833 
3834 		case IS_ARRAY:
3835 		{
3836 			zval *method = NULL;
3837 			zval *obj = NULL;
3838 
3839 			if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
3840 				obj = zend_hash_index_find_deref(Z_ARRVAL_P(callable), 0);
3841 				method = zend_hash_index_find_deref(Z_ARRVAL_P(callable), 1);
3842 			}
3843 
3844 			if (obj == NULL || method == NULL || Z_TYPE_P(method) != IS_STRING) {
3845 				return ZSTR_KNOWN(ZEND_STR_ARRAY_CAPITALIZED);
3846 			}
3847 
3848 			if (Z_TYPE_P(obj) == IS_STRING) {
3849 				return zend_create_member_string(Z_STR_P(obj), Z_STR_P(method));
3850 			} else if (Z_TYPE_P(obj) == IS_OBJECT) {
3851 				return zend_create_member_string(Z_OBJCE_P(obj)->name, Z_STR_P(method));
3852 			} else {
3853 				return ZSTR_KNOWN(ZEND_STR_ARRAY_CAPITALIZED);
3854 			}
3855 		}
3856 		case IS_OBJECT:
3857 		{
3858 			zend_class_entry *ce = Z_OBJCE_P(callable);
3859 			return zend_string_concat2(
3860 				ZSTR_VAL(ce->name), ZSTR_LEN(ce->name),
3861 				"::__invoke", sizeof("::__invoke") - 1);
3862 		}
3863 		case IS_REFERENCE:
3864 			callable = Z_REFVAL_P(callable);
3865 			goto try_again;
3866 		default:
3867 			return zval_get_string_func(callable);
3868 	}
3869 }
3870 /* }}} */
3871 
zend_get_callable_name(zval * callable)3872 ZEND_API zend_string *zend_get_callable_name(zval *callable) /* {{{ */
3873 {
3874 	return zend_get_callable_name_ex(callable, NULL);
3875 }
3876 /* }}} */
3877 
zend_is_callable_at_frame(zval * callable,zend_object * object,zend_execute_data * frame,uint32_t check_flags,zend_fcall_info_cache * fcc,char ** error)3878 ZEND_API bool zend_is_callable_at_frame(
3879 		zval *callable, zend_object *object, zend_execute_data *frame,
3880 		uint32_t check_flags, zend_fcall_info_cache *fcc, char **error) /* {{{ */
3881 {
3882 	bool ret;
3883 	zend_fcall_info_cache fcc_local;
3884 	bool strict_class = 0;
3885 
3886 	if (fcc == NULL) {
3887 		fcc = &fcc_local;
3888 	}
3889 	if (error) {
3890 		*error = NULL;
3891 	}
3892 
3893 	fcc->calling_scope = NULL;
3894 	fcc->called_scope = NULL;
3895 	fcc->function_handler = NULL;
3896 	fcc->object = NULL;
3897 
3898 again:
3899 	switch (Z_TYPE_P(callable)) {
3900 		case IS_STRING:
3901 			if (object) {
3902 				fcc->object = object;
3903 				fcc->calling_scope = object->ce;
3904 			}
3905 
3906 			if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3907 				fcc->called_scope = fcc->calling_scope;
3908 				return 1;
3909 			}
3910 
3911 check_func:
3912 			ret = zend_is_callable_check_func(callable, frame, fcc, strict_class, error, check_flags & IS_CALLABLE_SUPPRESS_DEPRECATIONS);
3913 			if (fcc == &fcc_local) {
3914 				zend_release_fcall_info_cache(fcc);
3915 			}
3916 			return ret;
3917 
3918 		case IS_ARRAY:
3919 			{
3920 				if (zend_hash_num_elements(Z_ARRVAL_P(callable)) != 2) {
3921 					if (error) *error = estrdup("array callback must have exactly two members");
3922 					return 0;
3923 				}
3924 
3925 				zval *obj = zend_hash_index_find(Z_ARRVAL_P(callable), 0);
3926 				zval *method = zend_hash_index_find(Z_ARRVAL_P(callable), 1);
3927 				if (!obj || !method) {
3928 					if (error) *error = estrdup("array callback has to contain indices 0 and 1");
3929 					return 0;
3930 				}
3931 
3932 				ZVAL_DEREF(obj);
3933 				if (Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_OBJECT) {
3934 					if (error) *error = estrdup("first array member is not a valid class name or object");
3935 					return 0;
3936 				}
3937 
3938 				ZVAL_DEREF(method);
3939 				if (Z_TYPE_P(method) != IS_STRING) {
3940 					if (error) *error = estrdup("second array member is not a valid method");
3941 					return 0;
3942 				}
3943 
3944 				if (Z_TYPE_P(obj) == IS_STRING) {
3945 					if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3946 						return 1;
3947 					}
3948 
3949 					if (!zend_is_callable_check_class(Z_STR_P(obj), get_scope(frame), frame, fcc, &strict_class, error, check_flags & IS_CALLABLE_SUPPRESS_DEPRECATIONS)) {
3950 						return 0;
3951 					}
3952 				} else {
3953 					ZEND_ASSERT(Z_TYPE_P(obj) == IS_OBJECT);
3954 					fcc->calling_scope = Z_OBJCE_P(obj); /* TBFixed: what if it's overloaded? */
3955 					fcc->object = Z_OBJ_P(obj);
3956 
3957 					if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3958 						fcc->called_scope = fcc->calling_scope;
3959 						return 1;
3960 					}
3961 				}
3962 
3963 				callable = method;
3964 				goto check_func;
3965 			}
3966 			return 0;
3967 		case IS_OBJECT:
3968 			if (Z_OBJ_HANDLER_P(callable, get_closure) && Z_OBJ_HANDLER_P(callable, get_closure)(Z_OBJ_P(callable), &fcc->calling_scope, &fcc->function_handler, &fcc->object, 1) == SUCCESS) {
3969 				fcc->called_scope = fcc->calling_scope;
3970 				if (fcc == &fcc_local) {
3971 					zend_release_fcall_info_cache(fcc);
3972 				}
3973 				return 1;
3974 			}
3975 			if (error) *error = estrdup("no array or string given");
3976 			return 0;
3977 		case IS_REFERENCE:
3978 			callable = Z_REFVAL_P(callable);
3979 			goto again;
3980 		default:
3981 			if (error) *error = estrdup("no array or string given");
3982 			return 0;
3983 	}
3984 }
3985 /* }}} */
3986 
zend_is_callable_ex(zval * callable,zend_object * object,uint32_t check_flags,zend_string ** callable_name,zend_fcall_info_cache * fcc,char ** error)3987 ZEND_API bool zend_is_callable_ex(zval *callable, zend_object *object, uint32_t check_flags, zend_string **callable_name, zend_fcall_info_cache *fcc, char **error) /* {{{ */
3988 {
3989 	/* Determine callability at the first parent user frame. */
3990 	zend_execute_data *frame = EG(current_execute_data);
3991 	while (frame && (!frame->func || !ZEND_USER_CODE(frame->func->type))) {
3992 		frame = frame->prev_execute_data;
3993 	}
3994 
3995 	bool ret = zend_is_callable_at_frame(callable, object, frame, check_flags, fcc, error);
3996 	if (callable_name) {
3997 		*callable_name = zend_get_callable_name_ex(callable, object);
3998 	}
3999 	return ret;
4000 }
4001 
zend_is_callable(zval * callable,uint32_t check_flags,zend_string ** callable_name)4002 ZEND_API bool zend_is_callable(zval *callable, uint32_t check_flags, zend_string **callable_name) /* {{{ */
4003 {
4004 	return zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, NULL);
4005 }
4006 /* }}} */
4007 
zend_make_callable(zval * callable,zend_string ** callable_name)4008 ZEND_API bool zend_make_callable(zval *callable, zend_string **callable_name) /* {{{ */
4009 {
4010 	zend_fcall_info_cache fcc;
4011 
4012 	if (zend_is_callable_ex(callable, NULL, IS_CALLABLE_SUPPRESS_DEPRECATIONS, callable_name, &fcc, NULL)) {
4013 		if (Z_TYPE_P(callable) == IS_STRING && fcc.calling_scope) {
4014 			zval_ptr_dtor_str(callable);
4015 			array_init(callable);
4016 			add_next_index_str(callable, zend_string_copy(fcc.calling_scope->name));
4017 			add_next_index_str(callable, zend_string_copy(fcc.function_handler->common.function_name));
4018 		}
4019 		zend_release_fcall_info_cache(&fcc);
4020 		return 1;
4021 	}
4022 	return 0;
4023 }
4024 /* }}} */
4025 
zend_fcall_info_init(zval * callable,uint32_t check_flags,zend_fcall_info * fci,zend_fcall_info_cache * fcc,zend_string ** callable_name,char ** error)4026 ZEND_API zend_result zend_fcall_info_init(zval *callable, uint32_t check_flags, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zend_string **callable_name, char **error) /* {{{ */
4027 {
4028 	if (!zend_is_callable_ex(callable, NULL, check_flags, callable_name, fcc, error)) {
4029 		return FAILURE;
4030 	}
4031 
4032 	fci->size = sizeof(*fci);
4033 	fci->object = fcc->object;
4034 	ZVAL_COPY_VALUE(&fci->function_name, callable);
4035 	fci->retval = NULL;
4036 	fci->param_count = 0;
4037 	fci->params = NULL;
4038 	fci->named_params = NULL;
4039 
4040 	return SUCCESS;
4041 }
4042 /* }}} */
4043 
zend_fcall_info_args_clear(zend_fcall_info * fci,bool free_mem)4044 ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, bool free_mem) /* {{{ */
4045 {
4046 	if (fci->params) {
4047 		zval *p = fci->params;
4048 		zval *end = p + fci->param_count;
4049 
4050 		while (p != end) {
4051 			i_zval_ptr_dtor(p);
4052 			p++;
4053 		}
4054 		if (free_mem) {
4055 			efree(fci->params);
4056 			fci->params = NULL;
4057 		}
4058 	}
4059 	fci->param_count = 0;
4060 }
4061 /* }}} */
4062 
zend_fcall_info_args_save(zend_fcall_info * fci,uint32_t * param_count,zval ** params)4063 ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, uint32_t *param_count, zval **params) /* {{{ */
4064 {
4065 	*param_count = fci->param_count;
4066 	*params = fci->params;
4067 	fci->param_count = 0;
4068 	fci->params = NULL;
4069 }
4070 /* }}} */
4071 
zend_fcall_info_args_restore(zend_fcall_info * fci,uint32_t param_count,zval * params)4072 ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, uint32_t param_count, zval *params) /* {{{ */
4073 {
4074 	zend_fcall_info_args_clear(fci, 1);
4075 	fci->param_count = param_count;
4076 	fci->params = params;
4077 }
4078 /* }}} */
4079 
zend_fcall_info_args_ex(zend_fcall_info * fci,zend_function * func,zval * args)4080 ZEND_API zend_result zend_fcall_info_args_ex(zend_fcall_info *fci, zend_function *func, zval *args) /* {{{ */
4081 {
4082 	zval *arg, *params;
4083 	uint32_t n = 1;
4084 
4085 	zend_fcall_info_args_clear(fci, !args);
4086 
4087 	if (!args) {
4088 		return SUCCESS;
4089 	}
4090 
4091 	if (Z_TYPE_P(args) != IS_ARRAY) {
4092 		return FAILURE;
4093 	}
4094 
4095 	fci->param_count = zend_hash_num_elements(Z_ARRVAL_P(args));
4096 	fci->params = params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
4097 
4098 	ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args), arg) {
4099 		if (func && !Z_ISREF_P(arg) && ARG_SHOULD_BE_SENT_BY_REF(func, n)) {
4100 			ZVAL_NEW_REF(params, arg);
4101 			Z_TRY_ADDREF_P(arg);
4102 		} else {
4103 			ZVAL_COPY(params, arg);
4104 		}
4105 		params++;
4106 		n++;
4107 	} ZEND_HASH_FOREACH_END();
4108 
4109 	return SUCCESS;
4110 }
4111 /* }}} */
4112 
zend_fcall_info_args(zend_fcall_info * fci,zval * args)4113 ZEND_API zend_result zend_fcall_info_args(zend_fcall_info *fci, zval *args) /* {{{ */
4114 {
4115 	return zend_fcall_info_args_ex(fci, NULL, args);
4116 }
4117 /* }}} */
4118 
zend_fcall_info_argp(zend_fcall_info * fci,uint32_t argc,zval * argv)4119 ZEND_API void zend_fcall_info_argp(zend_fcall_info *fci, uint32_t argc, zval *argv) /* {{{ */
4120 {
4121 	zend_fcall_info_args_clear(fci, !argc);
4122 
4123 	if (argc) {
4124 		fci->param_count = argc;
4125 		fci->params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
4126 
4127 		for (uint32_t i = 0; i < argc; ++i) {
4128 			ZVAL_COPY(&fci->params[i], &argv[i]);
4129 		}
4130 	}
4131 }
4132 /* }}} */
4133 
zend_fcall_info_argv(zend_fcall_info * fci,uint32_t argc,va_list * argv)4134 ZEND_API void zend_fcall_info_argv(zend_fcall_info *fci, uint32_t argc, va_list *argv) /* {{{ */
4135 {
4136 	zend_fcall_info_args_clear(fci, !argc);
4137 
4138 	if (argc) {
4139 		zval *arg;
4140 		fci->param_count = argc;
4141 		fci->params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
4142 
4143 		for (uint32_t i = 0; i < argc; ++i) {
4144 			arg = va_arg(*argv, zval *);
4145 			ZVAL_COPY(&fci->params[i], arg);
4146 		}
4147 	}
4148 }
4149 /* }}} */
4150 
zend_fcall_info_argn(zend_fcall_info * fci,uint32_t argc,...)4151 ZEND_API void zend_fcall_info_argn(zend_fcall_info *fci, uint32_t argc, ...) /* {{{ */
4152 {
4153 	va_list argv;
4154 
4155 	va_start(argv, argc);
4156 	zend_fcall_info_argv(fci, argc, &argv);
4157 	va_end(argv);
4158 }
4159 /* }}} */
4160 
zend_fcall_info_call(zend_fcall_info * fci,zend_fcall_info_cache * fcc,zval * retval_ptr,zval * args)4161 ZEND_API zend_result zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval *retval_ptr, zval *args) /* {{{ */
4162 {
4163 	zval retval, *org_params = NULL;
4164 	uint32_t org_count = 0;
4165 	zend_result result;
4166 
4167 	fci->retval = retval_ptr ? retval_ptr : &retval;
4168 	if (args) {
4169 		zend_fcall_info_args_save(fci, &org_count, &org_params);
4170 		zend_fcall_info_args(fci, args);
4171 	}
4172 	result = zend_call_function(fci, fcc);
4173 
4174 	if (!retval_ptr && Z_TYPE(retval) != IS_UNDEF) {
4175 		zval_ptr_dtor(&retval);
4176 	}
4177 	if (args) {
4178 		zend_fcall_info_args_restore(fci, org_count, org_params);
4179 	}
4180 	return result;
4181 }
4182 /* }}} */
4183 
zend_get_module_version(const char * module_name)4184 ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */
4185 {
4186 	zend_string *lname;
4187 	size_t name_len = strlen(module_name);
4188 	zend_module_entry *module;
4189 
4190 	lname = zend_string_alloc(name_len, 0);
4191 	zend_str_tolower_copy(ZSTR_VAL(lname), module_name, name_len);
4192 	module = zend_hash_find_ptr(&module_registry, lname);
4193 	zend_string_efree(lname);
4194 	return module ? module->version : NULL;
4195 }
4196 /* }}} */
4197 
is_persistent_class(zend_class_entry * ce)4198 static zend_always_inline bool is_persistent_class(zend_class_entry *ce) {
4199 	return (ce->type & ZEND_INTERNAL_CLASS)
4200 		&& ce->info.internal.module->type == MODULE_PERSISTENT;
4201 }
4202 
zend_declare_typed_property(zend_class_entry * ce,zend_string * name,zval * property,int access_type,zend_string * doc_comment,zend_type type)4203 ZEND_API zend_property_info *zend_declare_typed_property(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment, zend_type type) /* {{{ */
4204 {
4205 	zend_property_info *property_info, *property_info_ptr;
4206 
4207 	if (ZEND_TYPE_IS_SET(type)) {
4208 		ce->ce_flags |= ZEND_ACC_HAS_TYPE_HINTS;
4209 	}
4210 
4211 	if (ce->type == ZEND_INTERNAL_CLASS) {
4212 		property_info = pemalloc(sizeof(zend_property_info), 1);
4213 	} else {
4214 		property_info = zend_arena_alloc(&CG(arena), sizeof(zend_property_info));
4215 		if (Z_TYPE_P(property) == IS_CONSTANT_AST) {
4216 			ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
4217 			if (access_type & ZEND_ACC_STATIC) {
4218 				ce->ce_flags |= ZEND_ACC_HAS_AST_STATICS;
4219 			} else {
4220 				ce->ce_flags |= ZEND_ACC_HAS_AST_PROPERTIES;
4221 			}
4222 		}
4223 	}
4224 
4225 	if (Z_TYPE_P(property) == IS_STRING && !ZSTR_IS_INTERNED(Z_STR_P(property))) {
4226 		zval_make_interned_string(property);
4227 	}
4228 
4229 	if (!(access_type & ZEND_ACC_PPP_MASK)) {
4230 		access_type |= ZEND_ACC_PUBLIC;
4231 	}
4232 	if (access_type & ZEND_ACC_STATIC) {
4233 		if ((property_info_ptr = zend_hash_find_ptr(&ce->properties_info, name)) != NULL &&
4234 		    (property_info_ptr->flags & ZEND_ACC_STATIC) != 0) {
4235 			property_info->offset = property_info_ptr->offset;
4236 			zval_ptr_dtor(&ce->default_static_members_table[property_info->offset]);
4237 			if (property_info_ptr->doc_comment && property_info_ptr->ce == ce) {
4238 				zend_string_release(property_info_ptr->doc_comment);
4239 			}
4240 			zend_hash_del(&ce->properties_info, name);
4241 		} else {
4242 			property_info->offset = ce->default_static_members_count++;
4243 			ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
4244 		}
4245 		ZVAL_COPY_VALUE(&ce->default_static_members_table[property_info->offset], property);
4246 		if (!ZEND_MAP_PTR(ce->static_members_table)) {
4247 			if (ce->type == ZEND_INTERNAL_CLASS &&
4248 					ce->info.internal.module->type == MODULE_PERSISTENT) {
4249 				ZEND_MAP_PTR_NEW(ce->static_members_table);
4250 			}
4251 		}
4252 	} else {
4253 		zval *property_default_ptr;
4254 		if ((property_info_ptr = zend_hash_find_ptr(&ce->properties_info, name)) != NULL &&
4255 		    (property_info_ptr->flags & ZEND_ACC_STATIC) == 0) {
4256 			property_info->offset = property_info_ptr->offset;
4257 			zval_ptr_dtor(&ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)]);
4258 			if (property_info_ptr->doc_comment && property_info_ptr->ce == ce) {
4259 				zend_string_release_ex(property_info_ptr->doc_comment, 1);
4260 			}
4261 			zend_hash_del(&ce->properties_info, name);
4262 
4263 			ZEND_ASSERT(ce->type == ZEND_INTERNAL_CLASS);
4264 			ZEND_ASSERT(ce->properties_info_table != NULL);
4265 			ce->properties_info_table[OBJ_PROP_TO_NUM(property_info->offset)] = property_info;
4266 		} else {
4267 			property_info->offset = OBJ_PROP_TO_OFFSET(ce->default_properties_count);
4268 			ce->default_properties_count++;
4269 			ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
4270 
4271 			/* For user classes this is handled during linking */
4272 			if (ce->type == ZEND_INTERNAL_CLASS) {
4273 				ce->properties_info_table = perealloc(ce->properties_info_table, sizeof(zend_property_info *) * ce->default_properties_count, 1);
4274 				ce->properties_info_table[ce->default_properties_count - 1] = property_info;
4275 			}
4276 		}
4277 		property_default_ptr = &ce->default_properties_table[OBJ_PROP_TO_NUM(property_info->offset)];
4278 		ZVAL_COPY_VALUE(property_default_ptr, property);
4279 		Z_PROP_FLAG_P(property_default_ptr) = Z_ISUNDEF_P(property) ? IS_PROP_UNINIT : 0;
4280 	}
4281 	if (ce->type & ZEND_INTERNAL_CLASS) {
4282 		/* Must be interned to avoid ZTS data races */
4283 		if (is_persistent_class(ce)) {
4284 			name = zend_new_interned_string(zend_string_copy(name));
4285 		}
4286 
4287 		if (Z_REFCOUNTED_P(property)) {
4288 			zend_error_noreturn(E_CORE_ERROR, "Internal zvals cannot be refcounted");
4289 		}
4290 	}
4291 
4292 	if (access_type & ZEND_ACC_PUBLIC) {
4293 		property_info->name = zend_string_copy(name);
4294 	} else if (access_type & ZEND_ACC_PRIVATE) {
4295 		property_info->name = zend_mangle_property_name(ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), ZSTR_VAL(name), ZSTR_LEN(name), is_persistent_class(ce));
4296 	} else {
4297 		ZEND_ASSERT(access_type & ZEND_ACC_PROTECTED);
4298 		property_info->name = zend_mangle_property_name("*", 1, ZSTR_VAL(name), ZSTR_LEN(name), is_persistent_class(ce));
4299 	}
4300 
4301 	property_info->name = zend_new_interned_string(property_info->name);
4302 	property_info->flags = access_type;
4303 	property_info->doc_comment = doc_comment;
4304 	property_info->attributes = NULL;
4305 	property_info->ce = ce;
4306 	property_info->type = type;
4307 
4308 	if (is_persistent_class(ce)) {
4309 		zend_type *single_type;
4310 		ZEND_TYPE_FOREACH(property_info->type, single_type) {
4311 			// TODO Add support and test cases when gen_stub support added
4312 			ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*single_type));
4313 			if (ZEND_TYPE_HAS_NAME(*single_type)) {
4314 				zend_string *name = zend_new_interned_string(ZEND_TYPE_NAME(*single_type));
4315 				ZEND_TYPE_SET_PTR(*single_type, name);
4316 				zend_alloc_ce_cache(name);
4317 			}
4318 		} ZEND_TYPE_FOREACH_END();
4319 	}
4320 
4321 	zend_hash_update_ptr(&ce->properties_info, name, property_info);
4322 
4323 	return property_info;
4324 }
4325 /* }}} */
4326 
zend_try_assign_typed_ref_ex(zend_reference * ref,zval * val,bool strict)4327 ZEND_API zend_result zend_try_assign_typed_ref_ex(zend_reference *ref, zval *val, bool strict) /* {{{ */
4328 {
4329 	if (UNEXPECTED(!zend_verify_ref_assignable_zval(ref, val, strict))) {
4330 		zval_ptr_dtor(val);
4331 		return FAILURE;
4332 	} else {
4333 		zval_ptr_dtor(&ref->val);
4334 		ZVAL_COPY_VALUE(&ref->val, val);
4335 		return SUCCESS;
4336 	}
4337 }
4338 /* }}} */
4339 
zend_try_assign_typed_ref(zend_reference * ref,zval * val)4340 ZEND_API zend_result zend_try_assign_typed_ref(zend_reference *ref, zval *val) /* {{{ */
4341 {
4342 	return zend_try_assign_typed_ref_ex(ref, val, ZEND_ARG_USES_STRICT_TYPES());
4343 }
4344 /* }}} */
4345 
zend_try_assign_typed_ref_null(zend_reference * ref)4346 ZEND_API zend_result zend_try_assign_typed_ref_null(zend_reference *ref) /* {{{ */
4347 {
4348 	zval tmp;
4349 
4350 	ZVAL_NULL(&tmp);
4351 	return zend_try_assign_typed_ref(ref, &tmp);
4352 }
4353 /* }}} */
4354 
zend_try_assign_typed_ref_bool(zend_reference * ref,bool val)4355 ZEND_API zend_result zend_try_assign_typed_ref_bool(zend_reference *ref, bool val) /* {{{ */
4356 {
4357 	zval tmp;
4358 
4359 	ZVAL_BOOL(&tmp, val);
4360 	return zend_try_assign_typed_ref(ref, &tmp);
4361 }
4362 /* }}} */
4363 
zend_try_assign_typed_ref_long(zend_reference * ref,zend_long lval)4364 ZEND_API zend_result zend_try_assign_typed_ref_long(zend_reference *ref, zend_long lval) /* {{{ */
4365 {
4366 	zval tmp;
4367 
4368 	ZVAL_LONG(&tmp, lval);
4369 	return zend_try_assign_typed_ref(ref, &tmp);
4370 }
4371 /* }}} */
4372 
zend_try_assign_typed_ref_double(zend_reference * ref,double dval)4373 ZEND_API zend_result zend_try_assign_typed_ref_double(zend_reference *ref, double dval) /* {{{ */
4374 {
4375 	zval tmp;
4376 
4377 	ZVAL_DOUBLE(&tmp, dval);
4378 	return zend_try_assign_typed_ref(ref, &tmp);
4379 }
4380 /* }}} */
4381 
zend_try_assign_typed_ref_empty_string(zend_reference * ref)4382 ZEND_API zend_result zend_try_assign_typed_ref_empty_string(zend_reference *ref) /* {{{ */
4383 {
4384 	zval tmp;
4385 
4386 	ZVAL_EMPTY_STRING(&tmp);
4387 	return zend_try_assign_typed_ref(ref, &tmp);
4388 }
4389 /* }}} */
4390 
zend_try_assign_typed_ref_str(zend_reference * ref,zend_string * str)4391 ZEND_API zend_result zend_try_assign_typed_ref_str(zend_reference *ref, zend_string *str) /* {{{ */
4392 {
4393 	zval tmp;
4394 
4395 	ZVAL_STR(&tmp, str);
4396 	return zend_try_assign_typed_ref(ref, &tmp);
4397 }
4398 /* }}} */
4399 
zend_try_assign_typed_ref_string(zend_reference * ref,const char * string)4400 ZEND_API zend_result zend_try_assign_typed_ref_string(zend_reference *ref, const char *string) /* {{{ */
4401 {
4402 	zval tmp;
4403 
4404 	ZVAL_STRING(&tmp, string);
4405 	return zend_try_assign_typed_ref(ref, &tmp);
4406 }
4407 /* }}} */
4408 
zend_try_assign_typed_ref_stringl(zend_reference * ref,const char * string,size_t len)4409 ZEND_API zend_result zend_try_assign_typed_ref_stringl(zend_reference *ref, const char *string, size_t len) /* {{{ */
4410 {
4411 	zval tmp;
4412 
4413 	ZVAL_STRINGL(&tmp, string, len);
4414 	return zend_try_assign_typed_ref(ref, &tmp);
4415 }
4416 /* }}} */
4417 
zend_try_assign_typed_ref_arr(zend_reference * ref,zend_array * arr)4418 ZEND_API zend_result zend_try_assign_typed_ref_arr(zend_reference *ref, zend_array *arr) /* {{{ */
4419 {
4420 	zval tmp;
4421 
4422 	ZVAL_ARR(&tmp, arr);
4423 	return zend_try_assign_typed_ref(ref, &tmp);
4424 }
4425 /* }}} */
4426 
zend_try_assign_typed_ref_res(zend_reference * ref,zend_resource * res)4427 ZEND_API zend_result zend_try_assign_typed_ref_res(zend_reference *ref, zend_resource *res) /* {{{ */
4428 {
4429 	zval tmp;
4430 
4431 	ZVAL_RES(&tmp, res);
4432 	return zend_try_assign_typed_ref(ref, &tmp);
4433 }
4434 /* }}} */
4435 
zend_try_assign_typed_ref_zval(zend_reference * ref,zval * zv)4436 ZEND_API zend_result zend_try_assign_typed_ref_zval(zend_reference *ref, zval *zv) /* {{{ */
4437 {
4438 	zval tmp;
4439 
4440 	ZVAL_COPY_VALUE(&tmp, zv);
4441 	return zend_try_assign_typed_ref(ref, &tmp);
4442 }
4443 /* }}} */
4444 
zend_try_assign_typed_ref_zval_ex(zend_reference * ref,zval * zv,bool strict)4445 ZEND_API zend_result zend_try_assign_typed_ref_zval_ex(zend_reference *ref, zval *zv, bool strict) /* {{{ */
4446 {
4447 	zval tmp;
4448 
4449 	ZVAL_COPY_VALUE(&tmp, zv);
4450 	return zend_try_assign_typed_ref_ex(ref, &tmp, strict);
4451 }
4452 /* }}} */
4453 
zend_declare_property_ex(zend_class_entry * ce,zend_string * name,zval * property,int access_type,zend_string * doc_comment)4454 ZEND_API void zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment) /* {{{ */
4455 {
4456 	zend_declare_typed_property(ce, name, property, access_type, doc_comment, (zend_type) ZEND_TYPE_INIT_NONE(0));
4457 }
4458 /* }}} */
4459 
zend_declare_property(zend_class_entry * ce,const char * name,size_t name_length,zval * property,int access_type)4460 ZEND_API void zend_declare_property(zend_class_entry *ce, const char *name, size_t name_length, zval *property, int access_type) /* {{{ */
4461 {
4462 	zend_string *key = zend_string_init(name, name_length, is_persistent_class(ce));
4463 	zend_declare_property_ex(ce, key, property, access_type, NULL);
4464 	zend_string_release(key);
4465 }
4466 /* }}} */
4467 
zend_declare_property_null(zend_class_entry * ce,const char * name,size_t name_length,int access_type)4468 ZEND_API void zend_declare_property_null(zend_class_entry *ce, const char *name, size_t name_length, int access_type) /* {{{ */
4469 {
4470 	zval property;
4471 
4472 	ZVAL_NULL(&property);
4473 	zend_declare_property(ce, name, name_length, &property, access_type);
4474 }
4475 /* }}} */
4476 
zend_declare_property_bool(zend_class_entry * ce,const char * name,size_t name_length,zend_long value,int access_type)4477 ZEND_API void zend_declare_property_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type) /* {{{ */
4478 {
4479 	zval property;
4480 
4481 	ZVAL_BOOL(&property, value);
4482 	zend_declare_property(ce, name, name_length, &property, access_type);
4483 }
4484 /* }}} */
4485 
zend_declare_property_long(zend_class_entry * ce,const char * name,size_t name_length,zend_long value,int access_type)4486 ZEND_API void zend_declare_property_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type) /* {{{ */
4487 {
4488 	zval property;
4489 
4490 	ZVAL_LONG(&property, value);
4491 	zend_declare_property(ce, name, name_length, &property, access_type);
4492 }
4493 /* }}} */
4494 
zend_declare_property_double(zend_class_entry * ce,const char * name,size_t name_length,double value,int access_type)4495 ZEND_API void zend_declare_property_double(zend_class_entry *ce, const char *name, size_t name_length, double value, int access_type) /* {{{ */
4496 {
4497 	zval property;
4498 
4499 	ZVAL_DOUBLE(&property, value);
4500 	zend_declare_property(ce, name, name_length, &property, access_type);
4501 }
4502 /* }}} */
4503 
zend_declare_property_string(zend_class_entry * ce,const char * name,size_t name_length,const char * value,int access_type)4504 ZEND_API void zend_declare_property_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value, int access_type) /* {{{ */
4505 {
4506 	zval property;
4507 
4508 	ZVAL_NEW_STR(&property, zend_string_init(value, strlen(value), ce->type & ZEND_INTERNAL_CLASS));
4509 	zend_declare_property(ce, name, name_length, &property, access_type);
4510 }
4511 /* }}} */
4512 
zend_declare_property_stringl(zend_class_entry * ce,const char * name,size_t name_length,const char * value,size_t value_len,int access_type)4513 ZEND_API void zend_declare_property_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_len, int access_type) /* {{{ */
4514 {
4515 	zval property;
4516 
4517 	ZVAL_NEW_STR(&property, zend_string_init(value, value_len, ce->type & ZEND_INTERNAL_CLASS));
4518 	zend_declare_property(ce, name, name_length, &property, access_type);
4519 }
4520 /* }}} */
4521 
zend_declare_class_constant_ex(zend_class_entry * ce,zend_string * name,zval * value,int flags,zend_string * doc_comment)4522 ZEND_API zend_class_constant *zend_declare_class_constant_ex(zend_class_entry *ce, zend_string *name, zval *value, int flags, zend_string *doc_comment) /* {{{ */
4523 {
4524 	zend_class_constant *c;
4525 
4526 	if (ce->ce_flags & ZEND_ACC_INTERFACE) {
4527 		if (!(flags & ZEND_ACC_PUBLIC)) {
4528 			zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface constant %s::%s must be public", ZSTR_VAL(ce->name), ZSTR_VAL(name));
4529 		}
4530 	}
4531 
4532 	if (zend_string_equals_literal_ci(name, "class")) {
4533 		zend_error_noreturn(ce->type == ZEND_INTERNAL_CLASS ? E_CORE_ERROR : E_COMPILE_ERROR,
4534 				"A class constant must not be called 'class'; it is reserved for class name fetching");
4535 	}
4536 
4537 	if (Z_TYPE_P(value) == IS_STRING && !ZSTR_IS_INTERNED(Z_STR_P(value))) {
4538 		zval_make_interned_string(value);
4539 	}
4540 
4541 	if (ce->type == ZEND_INTERNAL_CLASS) {
4542 		c = pemalloc(sizeof(zend_class_constant), 1);
4543 	} else {
4544 		c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
4545 	}
4546 	ZVAL_COPY_VALUE(&c->value, value);
4547 	ZEND_CLASS_CONST_FLAGS(c) = flags;
4548 	c->doc_comment = doc_comment;
4549 	c->attributes = NULL;
4550 	c->ce = ce;
4551 	if (Z_TYPE_P(value) == IS_CONSTANT_AST) {
4552 		ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
4553 		ce->ce_flags |= ZEND_ACC_HAS_AST_CONSTANTS;
4554 		if (ce->type == ZEND_INTERNAL_CLASS && !ZEND_MAP_PTR(ce->mutable_data)) {
4555 			ZEND_MAP_PTR_NEW(ce->mutable_data);
4556 		}
4557 	}
4558 
4559 	if (!zend_hash_add_ptr(&ce->constants_table, name, c)) {
4560 		zend_error_noreturn(ce->type == ZEND_INTERNAL_CLASS ? E_CORE_ERROR : E_COMPILE_ERROR,
4561 			"Cannot redefine class constant %s::%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
4562 	}
4563 
4564 	return c;
4565 }
4566 /* }}} */
4567 
zend_declare_class_constant(zend_class_entry * ce,const char * name,size_t name_length,zval * value)4568 ZEND_API void zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value) /* {{{ */
4569 {
4570 	zend_string *key;
4571 
4572 	if (ce->type == ZEND_INTERNAL_CLASS) {
4573 		key = zend_string_init_interned(name, name_length, 1);
4574 	} else {
4575 		key = zend_string_init(name, name_length, 0);
4576 	}
4577 	zend_declare_class_constant_ex(ce, key, value, ZEND_ACC_PUBLIC, NULL);
4578 	zend_string_release(key);
4579 }
4580 /* }}} */
4581 
zend_declare_class_constant_null(zend_class_entry * ce,const char * name,size_t name_length)4582 ZEND_API void zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length) /* {{{ */
4583 {
4584 	zval constant;
4585 
4586 	ZVAL_NULL(&constant);
4587 	zend_declare_class_constant(ce, name, name_length, &constant);
4588 }
4589 /* }}} */
4590 
zend_declare_class_constant_long(zend_class_entry * ce,const char * name,size_t name_length,zend_long value)4591 ZEND_API void zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value) /* {{{ */
4592 {
4593 	zval constant;
4594 
4595 	ZVAL_LONG(&constant, value);
4596 	zend_declare_class_constant(ce, name, name_length, &constant);
4597 }
4598 /* }}} */
4599 
zend_declare_class_constant_bool(zend_class_entry * ce,const char * name,size_t name_length,bool value)4600 ZEND_API void zend_declare_class_constant_bool(zend_class_entry *ce, const char *name, size_t name_length, bool value) /* {{{ */
4601 {
4602 	zval constant;
4603 
4604 	ZVAL_BOOL(&constant, value);
4605 	zend_declare_class_constant(ce, name, name_length, &constant);
4606 }
4607 /* }}} */
4608 
zend_declare_class_constant_double(zend_class_entry * ce,const char * name,size_t name_length,double value)4609 ZEND_API void zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value) /* {{{ */
4610 {
4611 	zval constant;
4612 
4613 	ZVAL_DOUBLE(&constant, value);
4614 	zend_declare_class_constant(ce, name, name_length, &constant);
4615 }
4616 /* }}} */
4617 
zend_declare_class_constant_stringl(zend_class_entry * ce,const char * name,size_t name_length,const char * value,size_t value_length)4618 ZEND_API void zend_declare_class_constant_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_length) /* {{{ */
4619 {
4620 	zval constant;
4621 
4622 	ZVAL_NEW_STR(&constant, zend_string_init(value, value_length, ce->type & ZEND_INTERNAL_CLASS));
4623 	zend_declare_class_constant(ce, name, name_length, &constant);
4624 }
4625 /* }}} */
4626 
zend_declare_class_constant_string(zend_class_entry * ce,const char * name,size_t name_length,const char * value)4627 ZEND_API void zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value) /* {{{ */
4628 {
4629 	zend_declare_class_constant_stringl(ce, name, name_length, value, strlen(value));
4630 }
4631 /* }}} */
4632 
zend_update_property_ex(zend_class_entry * scope,zend_object * object,zend_string * name,zval * value)4633 ZEND_API void zend_update_property_ex(zend_class_entry *scope, zend_object *object, zend_string *name, zval *value) /* {{{ */
4634 {
4635 	zend_class_entry *old_scope = EG(fake_scope);
4636 
4637 	EG(fake_scope) = scope;
4638 
4639 	object->handlers->write_property(object, name, value, NULL);
4640 
4641 	EG(fake_scope) = old_scope;
4642 }
4643 /* }}} */
4644 
zend_update_property(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,zval * value)4645 ZEND_API void zend_update_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zval *value) /* {{{ */
4646 {
4647 	zend_string *property;
4648 	zend_class_entry *old_scope = EG(fake_scope);
4649 
4650 	EG(fake_scope) = scope;
4651 
4652 	property = zend_string_init(name, name_length, 0);
4653 	object->handlers->write_property(object, property, value, NULL);
4654 	zend_string_release_ex(property, 0);
4655 
4656 	EG(fake_scope) = old_scope;
4657 }
4658 /* }}} */
4659 
zend_update_property_null(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length)4660 ZEND_API void zend_update_property_null(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length) /* {{{ */
4661 {
4662 	zval tmp;
4663 
4664 	ZVAL_NULL(&tmp);
4665 	zend_update_property(scope, object, name, name_length, &tmp);
4666 }
4667 /* }}} */
4668 
zend_unset_property(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length)4669 ZEND_API void zend_unset_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length) /* {{{ */
4670 {
4671 	zend_string *property;
4672 	zend_class_entry *old_scope = EG(fake_scope);
4673 
4674 	EG(fake_scope) = scope;
4675 
4676 	property = zend_string_init(name, name_length, 0);
4677 	object->handlers->unset_property(object, property, 0);
4678 	zend_string_release_ex(property, 0);
4679 
4680 	EG(fake_scope) = old_scope;
4681 }
4682 /* }}} */
4683 
zend_update_property_bool(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,zend_long value)4684 ZEND_API void zend_update_property_bool(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_long value) /* {{{ */
4685 {
4686 	zval tmp;
4687 
4688 	ZVAL_BOOL(&tmp, value);
4689 	zend_update_property(scope, object, name, name_length, &tmp);
4690 }
4691 /* }}} */
4692 
zend_update_property_long(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,zend_long value)4693 ZEND_API void zend_update_property_long(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_long value) /* {{{ */
4694 {
4695 	zval tmp;
4696 
4697 	ZVAL_LONG(&tmp, value);
4698 	zend_update_property(scope, object, name, name_length, &tmp);
4699 }
4700 /* }}} */
4701 
zend_update_property_double(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,double value)4702 ZEND_API void zend_update_property_double(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, double value) /* {{{ */
4703 {
4704 	zval tmp;
4705 
4706 	ZVAL_DOUBLE(&tmp, value);
4707 	zend_update_property(scope, object, name, name_length, &tmp);
4708 }
4709 /* }}} */
4710 
zend_update_property_str(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,zend_string * value)4711 ZEND_API void zend_update_property_str(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, zend_string *value) /* {{{ */
4712 {
4713 	zval tmp;
4714 
4715 	ZVAL_STR(&tmp, value);
4716 	zend_update_property(scope, object, name, name_length, &tmp);
4717 }
4718 /* }}} */
4719 
zend_update_property_string(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,const char * value)4720 ZEND_API void zend_update_property_string(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, const char *value) /* {{{ */
4721 {
4722 	zval tmp;
4723 
4724 	ZVAL_STRING(&tmp, value);
4725 	Z_SET_REFCOUNT(tmp, 0);
4726 	zend_update_property(scope, object, name, name_length, &tmp);
4727 }
4728 /* }}} */
4729 
zend_update_property_stringl(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,const char * value,size_t value_len)4730 ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, const char *value, size_t value_len) /* {{{ */
4731 {
4732 	zval tmp;
4733 
4734 	ZVAL_STRINGL(&tmp, value, value_len);
4735 	Z_SET_REFCOUNT(tmp, 0);
4736 	zend_update_property(scope, object, name, name_length, &tmp);
4737 }
4738 /* }}} */
4739 
zend_update_static_property_ex(zend_class_entry * scope,zend_string * name,zval * value)4740 ZEND_API zend_result zend_update_static_property_ex(zend_class_entry *scope, zend_string *name, zval *value) /* {{{ */
4741 {
4742 	zval *property, tmp;
4743 	zend_property_info *prop_info;
4744 	zend_class_entry *old_scope = EG(fake_scope);
4745 
4746 	if (UNEXPECTED(!(scope->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
4747 		if (UNEXPECTED(zend_update_class_constants(scope)) != SUCCESS) {
4748 			return FAILURE;
4749 		}
4750 	}
4751 
4752 	EG(fake_scope) = scope;
4753 	property = zend_std_get_static_property_with_info(scope, name, BP_VAR_W, &prop_info);
4754 	EG(fake_scope) = old_scope;
4755 
4756 	if (!property) {
4757 		return FAILURE;
4758 	}
4759 
4760 	ZEND_ASSERT(!Z_ISREF_P(value));
4761 	Z_TRY_ADDREF_P(value);
4762 	if (ZEND_TYPE_IS_SET(prop_info->type)) {
4763 		ZVAL_COPY_VALUE(&tmp, value);
4764 		if (!zend_verify_property_type(prop_info, &tmp, /* strict */ 0)) {
4765 			Z_TRY_DELREF_P(value);
4766 			return FAILURE;
4767 		}
4768 		value = &tmp;
4769 	}
4770 
4771 	zend_assign_to_variable(property, value, IS_TMP_VAR, /* strict */ 0);
4772 	return SUCCESS;
4773 }
4774 /* }}} */
4775 
zend_update_static_property(zend_class_entry * scope,const char * name,size_t name_length,zval * value)4776 ZEND_API zend_result zend_update_static_property(zend_class_entry *scope, const char *name, size_t name_length, zval *value) /* {{{ */
4777 {
4778 	zend_string *key = zend_string_init(name, name_length, 0);
4779 	zend_result retval = zend_update_static_property_ex(scope, key, value);
4780 	zend_string_efree(key);
4781 	return retval;
4782 }
4783 /* }}} */
4784 
zend_update_static_property_null(zend_class_entry * scope,const char * name,size_t name_length)4785 ZEND_API zend_result zend_update_static_property_null(zend_class_entry *scope, const char *name, size_t name_length) /* {{{ */
4786 {
4787 	zval tmp;
4788 
4789 	ZVAL_NULL(&tmp);
4790 	return zend_update_static_property(scope, name, name_length, &tmp);
4791 }
4792 /* }}} */
4793 
zend_update_static_property_bool(zend_class_entry * scope,const char * name,size_t name_length,zend_long value)4794 ZEND_API zend_result zend_update_static_property_bool(zend_class_entry *scope, const char *name, size_t name_length, zend_long value) /* {{{ */
4795 {
4796 	zval tmp;
4797 
4798 	ZVAL_BOOL(&tmp, value);
4799 	return zend_update_static_property(scope, name, name_length, &tmp);
4800 }
4801 /* }}} */
4802 
zend_update_static_property_long(zend_class_entry * scope,const char * name,size_t name_length,zend_long value)4803 ZEND_API zend_result zend_update_static_property_long(zend_class_entry *scope, const char *name, size_t name_length, zend_long value) /* {{{ */
4804 {
4805 	zval tmp;
4806 
4807 	ZVAL_LONG(&tmp, value);
4808 	return zend_update_static_property(scope, name, name_length, &tmp);
4809 }
4810 /* }}} */
4811 
zend_update_static_property_double(zend_class_entry * scope,const char * name,size_t name_length,double value)4812 ZEND_API zend_result zend_update_static_property_double(zend_class_entry *scope, const char *name, size_t name_length, double value) /* {{{ */
4813 {
4814 	zval tmp;
4815 
4816 	ZVAL_DOUBLE(&tmp, value);
4817 	return zend_update_static_property(scope, name, name_length, &tmp);
4818 }
4819 /* }}} */
4820 
zend_update_static_property_string(zend_class_entry * scope,const char * name,size_t name_length,const char * value)4821 ZEND_API zend_result zend_update_static_property_string(zend_class_entry *scope, const char *name, size_t name_length, const char *value) /* {{{ */
4822 {
4823 	zval tmp;
4824 
4825 	ZVAL_STRING(&tmp, value);
4826 	Z_SET_REFCOUNT(tmp, 0);
4827 	return zend_update_static_property(scope, name, name_length, &tmp);
4828 }
4829 /* }}} */
4830 
zend_update_static_property_stringl(zend_class_entry * scope,const char * name,size_t name_length,const char * value,size_t value_len)4831 ZEND_API zend_result zend_update_static_property_stringl(zend_class_entry *scope, const char *name, size_t name_length, const char *value, size_t value_len) /* {{{ */
4832 {
4833 	zval tmp;
4834 
4835 	ZVAL_STRINGL(&tmp, value, value_len);
4836 	Z_SET_REFCOUNT(tmp, 0);
4837 	return zend_update_static_property(scope, name, name_length, &tmp);
4838 }
4839 /* }}} */
4840 
zend_read_property_ex(zend_class_entry * scope,zend_object * object,zend_string * name,bool silent,zval * rv)4841 ZEND_API zval *zend_read_property_ex(zend_class_entry *scope, zend_object *object, zend_string *name, bool silent, zval *rv) /* {{{ */
4842 {
4843 	zval *value;
4844 	zend_class_entry *old_scope = EG(fake_scope);
4845 
4846 	EG(fake_scope) = scope;
4847 
4848 	value = object->handlers->read_property(object, name, silent?BP_VAR_IS:BP_VAR_R, NULL, rv);
4849 
4850 	EG(fake_scope) = old_scope;
4851 	return value;
4852 }
4853 /* }}} */
4854 
zend_read_property(zend_class_entry * scope,zend_object * object,const char * name,size_t name_length,bool silent,zval * rv)4855 ZEND_API zval *zend_read_property(zend_class_entry *scope, zend_object *object, const char *name, size_t name_length, bool silent, zval *rv) /* {{{ */
4856 {
4857 	zval *value;
4858 	zend_string *str;
4859 
4860 	str = zend_string_init(name, name_length, 0);
4861 	value = zend_read_property_ex(scope, object, str, silent, rv);
4862 	zend_string_release_ex(str, 0);
4863 	return value;
4864 }
4865 /* }}} */
4866 
zend_read_static_property_ex(zend_class_entry * scope,zend_string * name,bool silent)4867 ZEND_API zval *zend_read_static_property_ex(zend_class_entry *scope, zend_string *name, bool silent) /* {{{ */
4868 {
4869 	zval *property;
4870 	zend_class_entry *old_scope = EG(fake_scope);
4871 
4872 	EG(fake_scope) = scope;
4873 	property = zend_std_get_static_property(scope, name, silent ? BP_VAR_IS : BP_VAR_R);
4874 	EG(fake_scope) = old_scope;
4875 
4876 	return property;
4877 }
4878 /* }}} */
4879 
zend_read_static_property(zend_class_entry * scope,const char * name,size_t name_length,bool silent)4880 ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, size_t name_length, bool silent) /* {{{ */
4881 {
4882 	zend_string *key = zend_string_init(name, name_length, 0);
4883 	zval *property = zend_read_static_property_ex(scope, key, silent);
4884 	zend_string_efree(key);
4885 	return property;
4886 }
4887 /* }}} */
4888 
zend_save_error_handling(zend_error_handling * current)4889 ZEND_API void zend_save_error_handling(zend_error_handling *current) /* {{{ */
4890 {
4891 	current->handling = EG(error_handling);
4892 	current->exception = EG(exception_class);
4893 }
4894 /* }}} */
4895 
zend_replace_error_handling(zend_error_handling_t error_handling,zend_class_entry * exception_class,zend_error_handling * current)4896 ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current) /* {{{ */
4897 {
4898 	if (current) {
4899 		zend_save_error_handling(current);
4900 	}
4901 	ZEND_ASSERT(error_handling == EH_THROW || exception_class == NULL);
4902 	EG(error_handling) = error_handling;
4903 	EG(exception_class) = exception_class;
4904 }
4905 /* }}} */
4906 
zend_restore_error_handling(zend_error_handling * saved)4907 ZEND_API void zend_restore_error_handling(zend_error_handling *saved) /* {{{ */
4908 {
4909 	EG(error_handling) = saved->handling;
4910 	EG(exception_class) = saved->exception;
4911 }
4912 /* }}} */
4913 
zend_get_object_type_case(const zend_class_entry * ce,bool upper_case)4914 ZEND_API ZEND_COLD const char *zend_get_object_type_case(const zend_class_entry *ce, bool upper_case) /* {{{ */
4915 {
4916 	if (ce->ce_flags & ZEND_ACC_TRAIT) {
4917 		return upper_case ? "Trait" : "trait";
4918 	} else if (ce->ce_flags & ZEND_ACC_INTERFACE) {
4919 		return upper_case ? "Interface" : "interface";
4920 	} else if (ce->ce_flags & ZEND_ACC_ENUM) {
4921 		return upper_case ? "Enum" : "enum";
4922 	} else {
4923 		return upper_case ? "Class" : "class";
4924 	}
4925 }
4926 /* }}} */
4927 
zend_is_iterable(zval * iterable)4928 ZEND_API bool zend_is_iterable(zval *iterable) /* {{{ */
4929 {
4930 	switch (Z_TYPE_P(iterable)) {
4931 		case IS_ARRAY:
4932 			return 1;
4933 		case IS_OBJECT:
4934 			return zend_class_implements_interface(Z_OBJCE_P(iterable), zend_ce_traversable);
4935 		default:
4936 			return 0;
4937 	}
4938 }
4939 /* }}} */
4940 
zend_is_countable(zval * countable)4941 ZEND_API bool zend_is_countable(zval *countable) /* {{{ */
4942 {
4943 	switch (Z_TYPE_P(countable)) {
4944 		case IS_ARRAY:
4945 			return 1;
4946 		case IS_OBJECT:
4947 			if (Z_OBJ_HT_P(countable)->count_elements) {
4948 				return 1;
4949 			}
4950 
4951 			return zend_class_implements_interface(Z_OBJCE_P(countable), zend_ce_countable);
4952 		default:
4953 			return 0;
4954 	}
4955 }
4956 /* }}} */
4957 
get_default_via_ast(zval * default_value_zval,const char * default_value)4958 static zend_result get_default_via_ast(zval *default_value_zval, const char *default_value) {
4959 	zend_ast *ast;
4960 	zend_arena *ast_arena;
4961 
4962 	zend_string *code = zend_string_concat3(
4963 		"<?php ", sizeof("<?php ") - 1, default_value, strlen(default_value), ";", 1);
4964 
4965 	ast = zend_compile_string_to_ast(code, &ast_arena, ZSTR_EMPTY_ALLOC());
4966 	zend_string_release(code);
4967 
4968 	if (!ast) {
4969 		return FAILURE;
4970 	}
4971 
4972 	zend_ast_list *statement_list = zend_ast_get_list(ast);
4973 	zend_ast **const_expr_ast_ptr = &statement_list->child[0];
4974 
4975 	zend_arena *original_ast_arena = CG(ast_arena);
4976 	uint32_t original_compiler_options = CG(compiler_options);
4977 	zend_file_context original_file_context;
4978 	CG(ast_arena) = ast_arena;
4979 	/* Disable constant substitution, to make getDefaultValueConstant() work. */
4980 	CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION | ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION;
4981 	zend_file_context_begin(&original_file_context);
4982 	zend_const_expr_to_zval(default_value_zval, const_expr_ast_ptr, /* allow_dynamic */ true);
4983 	CG(ast_arena) = original_ast_arena;
4984 	CG(compiler_options) = original_compiler_options;
4985 	zend_file_context_end(&original_file_context);
4986 
4987 	zend_ast_destroy(ast);
4988 	zend_arena_destroy(ast_arena);
4989 
4990 	return SUCCESS;
4991 }
4992 
try_parse_string(const char * str,size_t len,char quote)4993 static zend_string *try_parse_string(const char *str, size_t len, char quote) {
4994 	if (len == 0) {
4995 		return ZSTR_EMPTY_ALLOC();
4996 	}
4997 
4998 	for (size_t i = 0; i < len; i++) {
4999 		if (str[i] == '\\' || str[i] == quote) {
5000 			return NULL;
5001 		}
5002 	}
5003 	return zend_string_init(str, len, 0);
5004 }
5005 
zend_get_default_from_internal_arg_info(zval * default_value_zval,zend_internal_arg_info * arg_info)5006 ZEND_API zend_result zend_get_default_from_internal_arg_info(
5007 		zval *default_value_zval, zend_internal_arg_info *arg_info)
5008 {
5009 	const char *default_value = arg_info->default_value;
5010 	if (!default_value) {
5011 		return FAILURE;
5012 	}
5013 
5014 	/* Avoid going through the full AST machinery for some simple and common cases. */
5015 	size_t default_value_len = strlen(default_value);
5016 	zend_ulong lval;
5017 	if (default_value_len == sizeof("null")-1
5018 			&& !memcmp(default_value, "null", sizeof("null")-1)) {
5019 		ZVAL_NULL(default_value_zval);
5020 		return SUCCESS;
5021 	} else if (default_value_len == sizeof("true")-1
5022 			&& !memcmp(default_value, "true", sizeof("true")-1)) {
5023 		ZVAL_TRUE(default_value_zval);
5024 		return SUCCESS;
5025 	} else if (default_value_len == sizeof("false")-1
5026 			&& !memcmp(default_value, "false", sizeof("false")-1)) {
5027 		ZVAL_FALSE(default_value_zval);
5028 		return SUCCESS;
5029 	} else if (default_value_len >= 2
5030 			&& (default_value[0] == '\'' || default_value[0] == '"')
5031 			&& default_value[default_value_len - 1] == default_value[0]) {
5032 		zend_string *str = try_parse_string(
5033 			default_value + 1, default_value_len - 2, default_value[0]);
5034 		if (str) {
5035 			ZVAL_STR(default_value_zval, str);
5036 			return SUCCESS;
5037 		}
5038 	} else if (default_value_len == sizeof("[]")-1
5039 			&& !memcmp(default_value, "[]", sizeof("[]")-1)) {
5040 		ZVAL_EMPTY_ARRAY(default_value_zval);
5041 		return SUCCESS;
5042 	} else if (ZEND_HANDLE_NUMERIC_STR(default_value, default_value_len, lval)) {
5043 		ZVAL_LONG(default_value_zval, lval);
5044 		return SUCCESS;
5045 	}
5046 
5047 #if 0
5048 	fprintf(stderr, "Evaluating %s via AST\n", default_value);
5049 #endif
5050 	return get_default_via_ast(default_value_zval, default_value);
5051 }
5052