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