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