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