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