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, 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_COPY_VALUE(&object->properties_table[property_info->offset], prop);
1255                ZVAL_INDIRECT(prop, &object->properties_table[property_info->offset]);
1256            }
1257        } ZEND_HASH_FOREACH_END();
1258    }
1259}
1260/* }}} */
1261
1262ZEND_API void object_properties_load(zend_object *object, HashTable *properties TSRMLS_DC) /* {{{ */
1263{
1264    zval *prop, tmp;
1265    zend_string *key;
1266    zend_property_info *property_info;
1267
1268    ZEND_HASH_FOREACH_STR_KEY_VAL(properties, key, prop) {
1269        property_info = zend_get_property_info(object->ce, key, 1 TSRMLS_CC);
1270        if (property_info != ZEND_WRONG_PROPERTY_INFO &&
1271            property_info &&
1272            (property_info->flags & ZEND_ACC_STATIC) == 0) {
1273            zval_ptr_dtor(&object->properties_table[property_info->offset]);
1274            ZVAL_COPY_VALUE(&object->properties_table[property_info->offset], prop);
1275            zval_add_ref(&object->properties_table[property_info->offset]);
1276            if (object->properties) {
1277                ZVAL_INDIRECT(&tmp, &object->properties_table[property_info->offset]);
1278                zend_hash_update(object->properties, key, &tmp);
1279            }
1280        } else {
1281            if (!object->properties) {
1282                rebuild_object_properties(object);
1283            }
1284            prop = zend_hash_update(object->properties, key, prop);
1285            zval_add_ref(prop);
1286        }
1287    } ZEND_HASH_FOREACH_END();
1288}
1289/* }}} */
1290
1291/* This function requires 'properties' to contain all props declared in the
1292 * class and all props being public. If only a subset is given or the class
1293 * has protected members then you need to merge the properties separately by
1294 * calling zend_merge_properties(). */
1295ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
1296{
1297    if (class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
1298        char *what =   (class_type->ce_flags & ZEND_ACC_INTERFACE)                ? "interface"
1299                     :((class_type->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) ? "trait"
1300                     :                                                              "abstract class";
1301        zend_error(E_ERROR, "Cannot instantiate %s %s", what, class_type->name->val);
1302    }
1303
1304    zend_update_class_constants(class_type TSRMLS_CC);
1305
1306    if (class_type->create_object == NULL) {
1307        ZVAL_OBJ(arg, zend_objects_new(class_type TSRMLS_CC));
1308        if (properties) {
1309            object_properties_init_ex(Z_OBJ_P(arg), properties TSRMLS_CC);
1310        } else {
1311            object_properties_init(Z_OBJ_P(arg), class_type);
1312        }
1313    } else {
1314        ZVAL_OBJ(arg, class_type->create_object(class_type TSRMLS_CC));
1315    }
1316    return SUCCESS;
1317}
1318/* }}} */
1319
1320ZEND_API int _object_init_ex(zval *arg, zend_class_entry *class_type ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
1321{
1322    return _object_and_properties_init(arg, class_type, 0 ZEND_FILE_LINE_RELAY_CC TSRMLS_CC);
1323}
1324/* }}} */
1325
1326ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
1327{
1328    return _object_init_ex(arg, zend_standard_class_def ZEND_FILE_LINE_RELAY_CC TSRMLS_CC);
1329}
1330/* }}} */
1331
1332ZEND_API int add_assoc_function(zval *arg, const char *key, void (*function_ptr)(INTERNAL_FUNCTION_PARAMETERS)) /* {{{ */
1333{
1334    zend_error(E_WARNING, "add_assoc_function() is no longer supported");
1335    return FAILURE;
1336}
1337/* }}} */
1338
1339ZEND_API int add_assoc_long_ex(zval *arg, const char *key, size_t key_len, zend_long n) /* {{{ */
1340{
1341    zval *ret, tmp;
1342
1343    ZVAL_LONG(&tmp, n);
1344    ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1345    return ret ? SUCCESS : FAILURE;
1346}
1347/* }}} */
1348
1349ZEND_API int add_assoc_null_ex(zval *arg, const char *key, size_t key_len) /* {{{ */
1350{
1351    zval *ret, tmp;
1352
1353    ZVAL_NULL(&tmp);
1354    ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1355    return ret ? SUCCESS : FAILURE;
1356}
1357/* }}} */
1358
1359ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, size_t key_len, int b) /* {{{ */
1360{
1361    zval *ret, tmp;
1362
1363    ZVAL_BOOL(&tmp, b);
1364    ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1365    return ret ? SUCCESS : FAILURE;
1366}
1367/* }}} */
1368
1369ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r) /* {{{ */
1370{
1371    zval *ret, tmp;
1372
1373    ZVAL_RES(&tmp, r);
1374    ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1375    return ret ? SUCCESS : FAILURE;
1376}
1377/* }}} */
1378
1379ZEND_API int add_assoc_double_ex(zval *arg, const char *key, size_t key_len, double d) /* {{{ */
1380{
1381    zval *ret, tmp;
1382
1383    ZVAL_DOUBLE(&tmp, d);
1384    ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1385    return ret ? SUCCESS : FAILURE;
1386}
1387/* }}} */
1388
1389ZEND_API int add_assoc_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str) /* {{{ */
1390{
1391    zval *ret, tmp;
1392
1393    ZVAL_STR(&tmp, str);
1394    ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1395    return ret ? SUCCESS : FAILURE;
1396}
1397/* }}} */
1398
1399ZEND_API int add_assoc_string_ex(zval *arg, const char *key, size_t key_len, char *str) /* {{{ */
1400{
1401    zval *ret, tmp;
1402
1403    ZVAL_STRING(&tmp, str);
1404    ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1405    return ret ? SUCCESS : FAILURE;
1406}
1407/* }}} */
1408
1409ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, size_t key_len, char *str, size_t length) /* {{{ */
1410{
1411    zval *ret, tmp;
1412
1413    ZVAL_STRINGL(&tmp, str, length);
1414    ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1415    return ret ? SUCCESS : FAILURE;
1416}
1417/* }}} */
1418
1419ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, size_t key_len, zval *value) /* {{{ */
1420{
1421    zval *ret;
1422
1423    ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, value);
1424    return ret ? SUCCESS : FAILURE;
1425}
1426/* }}} */
1427
1428ZEND_API int add_index_long(zval *arg, zend_ulong index, zend_long n) /* {{{ */
1429{
1430    zval tmp;
1431
1432    ZVAL_LONG(&tmp, n);
1433    return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp) ? SUCCESS : FAILURE;
1434}
1435/* }}} */
1436
1437ZEND_API int add_index_null(zval *arg, zend_ulong index) /* {{{ */
1438{
1439    zval tmp;
1440
1441    ZVAL_NULL(&tmp);
1442    return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp) ? SUCCESS : FAILURE;
1443}
1444/* }}} */
1445
1446ZEND_API int add_index_bool(zval *arg, zend_ulong index, int b) /* {{{ */
1447{
1448    zval tmp;
1449
1450    ZVAL_BOOL(&tmp, b);
1451    return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp) ? SUCCESS : FAILURE;
1452}
1453/* }}} */
1454
1455ZEND_API int add_index_resource(zval *arg, zend_ulong index, zend_resource *r) /* {{{ */
1456{
1457    zval tmp;
1458
1459    ZVAL_RES(&tmp, r);
1460    return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp) ? SUCCESS : FAILURE;
1461}
1462/* }}} */
1463
1464ZEND_API int add_index_double(zval *arg, zend_ulong index, double d) /* {{{ */
1465{
1466    zval tmp;
1467
1468    ZVAL_DOUBLE(&tmp, d);
1469    return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp) ? SUCCESS : FAILURE;
1470}
1471/* }}} */
1472
1473ZEND_API int add_index_str(zval *arg, zend_ulong index, zend_string *str) /* {{{ */
1474{
1475    zval tmp;
1476
1477    ZVAL_STR(&tmp, str);
1478    return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp) ? SUCCESS : FAILURE;
1479}
1480/* }}} */
1481
1482ZEND_API int add_index_string(zval *arg, zend_ulong index, const char *str) /* {{{ */
1483{
1484    zval tmp;
1485
1486    ZVAL_STRING(&tmp, str);
1487    return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp) ? SUCCESS : FAILURE;
1488}
1489/* }}} */
1490
1491ZEND_API int add_index_stringl(zval *arg, zend_ulong index, const char *str, size_t length) /* {{{ */
1492{
1493    zval tmp;
1494
1495    ZVAL_STRINGL(&tmp, str, length);
1496    return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp) ? SUCCESS : FAILURE;
1497}
1498/* }}} */
1499
1500ZEND_API int add_index_zval(zval *arg, zend_ulong index, zval *value) /* {{{ */
1501{
1502    return zend_hash_index_update(Z_ARRVAL_P(arg), index, value) ? SUCCESS : FAILURE;
1503}
1504/* }}} */
1505
1506ZEND_API int add_next_index_long(zval *arg, zend_long n) /* {{{ */
1507{
1508    zval tmp;
1509
1510    ZVAL_LONG(&tmp, n);
1511    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1512}
1513/* }}} */
1514
1515ZEND_API int add_next_index_null(zval *arg) /* {{{ */
1516{
1517    zval tmp;
1518
1519    ZVAL_NULL(&tmp);
1520    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1521}
1522/* }}} */
1523
1524ZEND_API int add_next_index_bool(zval *arg, int b) /* {{{ */
1525{
1526    zval tmp;
1527
1528    ZVAL_BOOL(&tmp, b);
1529    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1530}
1531/* }}} */
1532
1533ZEND_API int add_next_index_resource(zval *arg, zend_resource *r) /* {{{ */
1534{
1535    zval tmp;
1536
1537    ZVAL_RES(&tmp, r);
1538    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1539}
1540/* }}} */
1541
1542ZEND_API int add_next_index_double(zval *arg, double d) /* {{{ */
1543{
1544    zval tmp;
1545
1546    ZVAL_DOUBLE(&tmp, d);
1547    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1548}
1549/* }}} */
1550
1551ZEND_API int add_next_index_str(zval *arg, zend_string *str) /* {{{ */
1552{
1553    zval tmp;
1554
1555    ZVAL_STR(&tmp, str);
1556    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1557}
1558/* }}} */
1559
1560ZEND_API int add_next_index_string(zval *arg, const char *str) /* {{{ */
1561{
1562    zval tmp;
1563
1564    ZVAL_STRING(&tmp, str);
1565    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1566}
1567/* }}} */
1568
1569ZEND_API int add_next_index_stringl(zval *arg, const char *str, size_t length) /* {{{ */
1570{
1571    zval tmp;
1572
1573    ZVAL_STRINGL(&tmp, str, length);
1574    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp) ? SUCCESS : FAILURE;
1575}
1576/* }}} */
1577
1578ZEND_API int add_next_index_zval(zval *arg, zval *value) /* {{{ */
1579{
1580    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), value) ? SUCCESS : FAILURE;
1581}
1582/* }}} */
1583
1584ZEND_API zval *add_get_assoc_string_ex(zval *arg, const char *key, uint key_len, const char *str) /* {{{ */
1585{
1586    zval tmp, *ret;
1587
1588    ZVAL_STRING(&tmp, str);
1589    ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1590    return ret;
1591}
1592/* }}} */
1593
1594ZEND_API zval *add_get_assoc_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, size_t length) /* {{{ */
1595{
1596    zval tmp, *ret;
1597
1598    ZVAL_STRINGL(&tmp, str, length);
1599    ret = zend_symtable_str_update(Z_ARRVAL_P(arg), key, key_len, &tmp);
1600    return ret;
1601}
1602/* }}} */
1603
1604ZEND_API zval *add_get_index_long(zval *arg, zend_ulong index, zend_long l) /* {{{ */
1605{
1606    zval tmp;
1607
1608    ZVAL_LONG(&tmp, l);
1609    return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1610}
1611/* }}} */
1612
1613ZEND_API zval *add_get_index_double(zval *arg, zend_ulong index, double d) /* {{{ */
1614{
1615    zval tmp;
1616
1617    ZVAL_DOUBLE(&tmp, d);
1618    return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1619}
1620/* }}} */
1621
1622ZEND_API zval *add_get_index_str(zval *arg, zend_ulong index, zend_string *str) /* {{{ */
1623{
1624    zval tmp;
1625
1626    ZVAL_STR(&tmp, str);
1627    return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1628}
1629/* }}} */
1630
1631ZEND_API zval *add_get_index_string(zval *arg, zend_ulong index, const char *str) /* {{{ */
1632{
1633    zval tmp;
1634
1635    ZVAL_STRING(&tmp, str);
1636    return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1637}
1638/* }}} */
1639
1640ZEND_API zval *add_get_index_stringl(zval *arg, zend_ulong index, const char *str, size_t length) /* {{{ */
1641{
1642    zval tmp;
1643
1644    ZVAL_STRINGL(&tmp, str, length);
1645    return zend_hash_index_update(Z_ARRVAL_P(arg), index, &tmp);
1646}
1647/* }}} */
1648
1649ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value TSRMLS_DC) /* {{{ */
1650{
1651    zval *result;
1652
1653    switch (Z_TYPE_P(key)) {
1654        case IS_STRING:
1655            result = zend_symtable_update(ht, Z_STR_P(key), value);
1656            break;
1657        case IS_NULL:
1658            result = zend_symtable_update(ht, STR_EMPTY_ALLOC(), value);
1659            break;
1660        case IS_RESOURCE:
1661            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));
1662            result = zend_hash_index_update(ht, Z_RES_HANDLE_P(key), value);
1663            break;
1664        case IS_FALSE:
1665            result = zend_hash_index_update(ht, 0, value);
1666            break;
1667        case IS_TRUE:
1668            result = zend_hash_index_update(ht, 1, value);
1669            break;
1670        case IS_LONG:
1671            result = zend_hash_index_update(ht, Z_LVAL_P(key), value);
1672            break;
1673        case IS_DOUBLE:
1674            result = zend_hash_index_update(ht, zend_dval_to_lval(Z_DVAL_P(key)), value);
1675            break;
1676        default:
1677            zend_error(E_WARNING, "Illegal offset type");
1678            result = NULL;
1679    }
1680
1681    if (result) {
1682        if (Z_REFCOUNTED_P(result)) {
1683            Z_ADDREF_P(result);
1684        }
1685        return SUCCESS;
1686    } else {
1687        return FAILURE;
1688    }
1689}
1690/* }}} */
1691
1692ZEND_API int add_property_long_ex(zval *arg, const char *key, size_t key_len, zend_long n TSRMLS_DC) /* {{{ */
1693{
1694    zval tmp;
1695    zval z_key;
1696
1697    ZVAL_LONG(&tmp, n);
1698    ZVAL_STRINGL(&z_key, key, key_len);
1699    Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL TSRMLS_CC);
1700    zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1701    zval_ptr_dtor(&z_key);
1702    return SUCCESS;
1703}
1704/* }}} */
1705
1706ZEND_API int add_property_bool_ex(zval *arg, const char *key, size_t key_len, zend_long b TSRMLS_DC) /* {{{ */
1707{
1708    zval tmp;
1709    zval z_key;
1710
1711    ZVAL_BOOL(&tmp, b);
1712    ZVAL_STRINGL(&z_key, key, key_len);
1713    Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL TSRMLS_CC);
1714    zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1715    zval_ptr_dtor(&z_key);
1716    return SUCCESS;
1717}
1718/* }}} */
1719
1720ZEND_API int add_property_null_ex(zval *arg, const char *key, size_t key_len TSRMLS_DC) /* {{{ */
1721{
1722    zval tmp;
1723    zval z_key;
1724
1725    ZVAL_NULL(&tmp);
1726    ZVAL_STRINGL(&z_key, key, key_len);
1727    Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL TSRMLS_CC);
1728    zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1729    zval_ptr_dtor(&z_key);
1730    return SUCCESS;
1731}
1732/* }}} */
1733
1734ZEND_API int add_property_resource_ex(zval *arg, const char *key, size_t key_len, zend_resource *r TSRMLS_DC) /* {{{ */
1735{
1736    zval tmp;
1737    zval z_key;
1738
1739    ZVAL_RES(&tmp, r);
1740    ZVAL_STRINGL(&z_key, key, key_len);
1741    Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL TSRMLS_CC);
1742    zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1743    zval_ptr_dtor(&z_key);
1744    return SUCCESS;
1745}
1746/* }}} */
1747
1748ZEND_API int add_property_double_ex(zval *arg, const char *key, size_t key_len, double d TSRMLS_DC) /* {{{ */
1749{
1750    zval tmp;
1751    zval z_key;
1752
1753    ZVAL_DOUBLE(&tmp, d);
1754    ZVAL_STRINGL(&z_key, key, key_len);
1755    Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL TSRMLS_CC);
1756    zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1757    zval_ptr_dtor(&z_key);
1758    return SUCCESS;
1759}
1760/* }}} */
1761
1762ZEND_API int add_property_str_ex(zval *arg, const char *key, size_t key_len, zend_string *str TSRMLS_DC) /* {{{ */
1763{
1764    zval tmp;
1765    zval z_key;
1766
1767    ZVAL_STR(&tmp, str);
1768    ZVAL_STRINGL(&z_key, key, key_len);
1769    Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL TSRMLS_CC);
1770    zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1771    zval_ptr_dtor(&z_key);
1772    return SUCCESS;
1773}
1774/* }}} */
1775
1776ZEND_API int add_property_string_ex(zval *arg, const char *key, size_t key_len, const char *str TSRMLS_DC) /* {{{ */
1777{
1778    zval tmp;
1779    zval z_key;
1780
1781    ZVAL_STRING(&tmp, str);
1782    ZVAL_STRINGL(&z_key, key, key_len);
1783    Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL TSRMLS_CC);
1784    zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1785    zval_ptr_dtor(&z_key);
1786    return SUCCESS;
1787}
1788/* }}} */
1789
1790ZEND_API int add_property_stringl_ex(zval *arg, const char *key, size_t key_len, const char *str, size_t length TSRMLS_DC) /* {{{ */
1791{
1792    zval tmp;
1793    zval z_key;
1794
1795    ZVAL_STRINGL(&tmp, str, length);
1796    ZVAL_STRINGL(&z_key, key, key_len);
1797    Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, &tmp, NULL TSRMLS_CC);
1798    zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1799    zval_ptr_dtor(&z_key);
1800    return SUCCESS;
1801}
1802/* }}} */
1803
1804ZEND_API int add_property_zval_ex(zval *arg, const char *key, size_t key_len, zval *value TSRMLS_DC) /* {{{ */
1805{
1806    zval z_key;
1807
1808    ZVAL_STRINGL(&z_key, key, key_len);
1809    Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, value, NULL TSRMLS_CC);
1810    zval_ptr_dtor(&z_key);
1811    return SUCCESS;
1812}
1813/* }}} */
1814
1815ZEND_API int zend_startup_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */
1816{
1817    size_t name_len;
1818    zend_string *lcname;
1819
1820    if (module->module_started) {
1821        return SUCCESS;
1822    }
1823    module->module_started = 1;
1824
1825    /* Check module dependencies */
1826    if (module->deps) {
1827        const zend_module_dep *dep = module->deps;
1828
1829        while (dep->name) {
1830            if (dep->type == MODULE_DEP_REQUIRED) {
1831                zend_module_entry *req_mod;
1832
1833                name_len = strlen(dep->name);
1834                lcname = zend_string_alloc(name_len, 0);
1835                zend_str_tolower_copy(lcname->val, dep->name, name_len);
1836
1837                if ((req_mod = zend_hash_find_ptr(&module_registry, lcname)) == NULL || !req_mod->module_started) {
1838                    zend_string_free(lcname);
1839                    /* TODO: Check version relationship */
1840                    zend_error(E_CORE_WARNING, "Cannot load module '%s' because required module '%s' is not loaded", module->name, dep->name);
1841                    module->module_started = 0;
1842                    return FAILURE;
1843                }
1844                zend_string_free(lcname);
1845            }
1846            ++dep;
1847        }
1848    }
1849
1850    /* Initialize module globals */
1851    if (module->globals_size) {
1852#ifdef ZTS
1853        ts_allocate_id(module->globals_id_ptr, module->globals_size, (ts_allocate_ctor) module->globals_ctor, (ts_allocate_dtor) module->globals_dtor);
1854#else
1855        if (module->globals_ctor) {
1856            module->globals_ctor(module->globals_ptr TSRMLS_CC);
1857        }
1858#endif
1859    }
1860    if (module->module_startup_func) {
1861        EG(current_module) = module;
1862        if (module->module_startup_func(module->type, module->module_number TSRMLS_CC)==FAILURE) {
1863            zend_error(E_CORE_ERROR,"Unable to start %s module", module->name);
1864            EG(current_module) = NULL;
1865            return FAILURE;
1866        }
1867        EG(current_module) = NULL;
1868    }
1869    return SUCCESS;
1870}
1871/* }}} */
1872
1873static int zend_startup_module_zval(zval *zv TSRMLS_DC) /* {{{ */
1874{
1875    zend_module_entry *module = Z_PTR_P(zv);
1876
1877    return zend_startup_module_ex(module TSRMLS_CC);
1878}
1879/* }}} */
1880
1881
1882static void zend_sort_modules(void *base, size_t count, size_t siz, compare_func_t compare TSRMLS_DC) /* {{{ */
1883{
1884    Bucket *b1 = base;
1885    Bucket *b2;
1886    Bucket *end = b1 + count;
1887    Bucket tmp;
1888    zend_module_entry *m, *r;
1889
1890    while (b1 < end) {
1891try_again:
1892        m = (zend_module_entry*)Z_PTR(b1->val);
1893        if (!m->module_started && m->deps) {
1894            const zend_module_dep *dep = m->deps;
1895            while (dep->name) {
1896                if (dep->type == MODULE_DEP_REQUIRED || dep->type == MODULE_DEP_OPTIONAL) {
1897                    b2 = b1 + 1;
1898                    while (b2 < end) {
1899                        r = (zend_module_entry*)Z_PTR(b2->val);
1900                        if (strcasecmp(dep->name, r->name) == 0) {
1901                            tmp = *b1;
1902                            *b1 = *b2;
1903                            *b2 = tmp;
1904                            goto try_again;
1905                        }
1906                        b2++;
1907                    }
1908                }
1909                dep++;
1910            }
1911        }
1912        b1++;
1913    }
1914}
1915/* }}} */
1916
1917ZEND_API void zend_collect_module_handlers(TSRMLS_D) /* {{{ */
1918{
1919    zend_module_entry *module;
1920    int startup_count = 0;
1921    int shutdown_count = 0;
1922    int post_deactivate_count = 0;
1923    zend_class_entry *ce;
1924    int class_count = 0;
1925
1926    /* Collect extensions with request startup/shutdown handlers */
1927    ZEND_HASH_FOREACH_PTR(&module_registry, module) {
1928        if (module->request_startup_func) {
1929            startup_count++;
1930        }
1931        if (module->request_shutdown_func) {
1932            shutdown_count++;
1933        }
1934        if (module->post_deactivate_func) {
1935            post_deactivate_count++;
1936        }
1937    } ZEND_HASH_FOREACH_END();
1938    module_request_startup_handlers = (zend_module_entry**)malloc(
1939        sizeof(zend_module_entry*) *
1940        (startup_count + 1 +
1941         shutdown_count + 1 +
1942         post_deactivate_count + 1));
1943    module_request_startup_handlers[startup_count] = NULL;
1944    module_request_shutdown_handlers = module_request_startup_handlers + startup_count + 1;
1945    module_request_shutdown_handlers[shutdown_count] = NULL;
1946    module_post_deactivate_handlers = module_request_shutdown_handlers + shutdown_count + 1;
1947    module_post_deactivate_handlers[post_deactivate_count] = NULL;
1948    startup_count = 0;
1949
1950    ZEND_HASH_FOREACH_PTR(&module_registry, module) {
1951        if (module->request_startup_func) {
1952            module_request_startup_handlers[startup_count++] = module;
1953        }
1954        if (module->request_shutdown_func) {
1955            module_request_shutdown_handlers[--shutdown_count] = module;
1956        }
1957        if (module->post_deactivate_func) {
1958            module_post_deactivate_handlers[--post_deactivate_count] = module;
1959        }
1960    } ZEND_HASH_FOREACH_END();
1961
1962    /* Collect internal classes with static members */
1963    ZEND_HASH_FOREACH_PTR(CG(class_table), ce) {
1964        if (ce->type == ZEND_INTERNAL_CLASS &&
1965            ce->default_static_members_count > 0) {
1966            class_count++;
1967        }
1968    } ZEND_HASH_FOREACH_END();
1969
1970    class_cleanup_handlers = (zend_class_entry**)malloc(
1971        sizeof(zend_class_entry*) *
1972        (class_count + 1));
1973    class_cleanup_handlers[class_count] = NULL;
1974
1975    if (class_count) {
1976        ZEND_HASH_FOREACH_PTR(CG(class_table), ce) {
1977            if (ce->type == ZEND_INTERNAL_CLASS &&
1978                ce->default_static_members_count > 0) {
1979                class_cleanup_handlers[--class_count] = ce;
1980            }
1981        } ZEND_HASH_FOREACH_END();
1982    }
1983}
1984/* }}} */
1985
1986ZEND_API int zend_startup_modules(TSRMLS_D) /* {{{ */
1987{
1988    zend_hash_sort(&module_registry, zend_sort_modules, NULL, 0 TSRMLS_CC);
1989    zend_hash_apply(&module_registry, zend_startup_module_zval TSRMLS_CC);
1990    return SUCCESS;
1991}
1992/* }}} */
1993
1994ZEND_API void zend_destroy_modules(void) /* {{{ */
1995{
1996    free(class_cleanup_handlers);
1997    free(module_request_startup_handlers);
1998    zend_hash_graceful_reverse_destroy(&module_registry);
1999}
2000/* }}} */
2001
2002ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */
2003{
2004    size_t name_len;
2005    zend_string *lcname;
2006    zend_module_entry *module_ptr;
2007
2008    if (!module) {
2009        return NULL;
2010    }
2011
2012#if 0
2013    zend_printf("%s: Registering module %d\n", module->name, module->module_number);
2014#endif
2015
2016    /* Check module dependencies */
2017    if (module->deps) {
2018        const zend_module_dep *dep = module->deps;
2019
2020        while (dep->name) {
2021            if (dep->type == MODULE_DEP_CONFLICTS) {
2022                name_len = strlen(dep->name);
2023                lcname = zend_string_alloc(name_len, 0);
2024                zend_str_tolower_copy(lcname->val, dep->name, name_len);
2025
2026                if (zend_hash_exists(&module_registry, lcname)) {
2027                    zend_string_free(lcname);
2028                    /* TODO: Check version relationship */
2029                    zend_error(E_CORE_WARNING, "Cannot load module '%s' because conflicting module '%s' is already loaded", module->name, dep->name);
2030                    return NULL;
2031                }
2032                zend_string_free(lcname);
2033            }
2034            ++dep;
2035        }
2036    }
2037
2038    name_len = strlen(module->name);
2039    lcname = zend_string_alloc(name_len, 1);
2040    zend_str_tolower_copy(lcname->val, module->name, name_len);
2041
2042    if ((module_ptr = zend_hash_add_mem(&module_registry, lcname, module, sizeof(zend_module_entry))) == NULL) {
2043        zend_error(E_CORE_WARNING, "Module '%s' already loaded", module->name);
2044        zend_string_release(lcname);
2045        return NULL;
2046    }
2047    zend_string_release(lcname);
2048    module = module_ptr;
2049    EG(current_module) = module;
2050
2051    if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type TSRMLS_CC)==FAILURE) {
2052        EG(current_module) = NULL;
2053        zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name);
2054        return NULL;
2055    }
2056
2057    EG(current_module) = NULL;
2058    return module;
2059}
2060/* }}} */
2061
2062ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *module TSRMLS_DC) /* {{{ */
2063{
2064    module->module_number = zend_next_free_module();
2065    module->type = MODULE_PERSISTENT;
2066    return zend_register_module_ex(module TSRMLS_CC);
2067}
2068/* }}} */
2069
2070ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, int error_type TSRMLS_DC) /* {{{ */
2071{
2072    char lcname[16];
2073    size_t name_len;
2074
2075    /* we don't care if the function name is longer, in fact lowercasing only
2076     * the beginning of the name speeds up the check process */
2077    name_len = fptr->common.function_name->len;
2078    zend_str_tolower_copy(lcname, fptr->common.function_name->val, MIN(name_len, sizeof(lcname)-1));
2079    lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
2080
2081    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) {
2082        zend_error(error_type, "Destructor %s::%s() cannot take arguments", ce->name->val, ZEND_DESTRUCTOR_FUNC_NAME);
2083    } 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) {
2084        zend_error(error_type, "Method %s::%s() cannot accept any arguments", ce->name->val, ZEND_CLONE_FUNC_NAME);
2085    } else if (name_len == sizeof(ZEND_GET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME) - 1)) {
2086        if (fptr->common.num_args != 1) {
2087            zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name->val, ZEND_GET_FUNC_NAME);
2088        } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
2089            zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name->val, ZEND_GET_FUNC_NAME);
2090        }
2091    } else if (name_len == sizeof(ZEND_SET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME) - 1)) {
2092        if (fptr->common.num_args != 2) {
2093            zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name->val, ZEND_SET_FUNC_NAME);
2094        } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
2095            zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name->val, ZEND_SET_FUNC_NAME);
2096        }
2097    } else if (name_len == sizeof(ZEND_UNSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME) - 1)) {
2098        if (fptr->common.num_args != 1) {
2099            zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name->val, ZEND_UNSET_FUNC_NAME);
2100        } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
2101            zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name->val, ZEND_UNSET_FUNC_NAME);
2102        }
2103    } else if (name_len == sizeof(ZEND_ISSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME) - 1)) {
2104        if (fptr->common.num_args != 1) {
2105            zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name->val, ZEND_ISSET_FUNC_NAME);
2106        } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
2107            zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name->val, ZEND_ISSET_FUNC_NAME);
2108        }
2109    } else if (name_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME) - 1)) {
2110        if (fptr->common.num_args != 2) {
2111            zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name->val, ZEND_CALL_FUNC_NAME);
2112        } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
2113            zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name->val, ZEND_CALL_FUNC_NAME);
2114        }
2115    } else if (name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1 &&
2116        !memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1)
2117    ) {
2118        if (fptr->common.num_args != 2) {
2119            zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name->val, ZEND_CALLSTATIC_FUNC_NAME);
2120        } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
2121            zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name->val, ZEND_CALLSTATIC_FUNC_NAME);
2122        }
2123    } else if (name_len == sizeof(ZEND_TOSTRING_FUNC_NAME) - 1 &&
2124        !memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && fptr->common.num_args != 0
2125    ) {
2126        zend_error(error_type, "Method %s::%s() cannot take arguments", ce->name->val, ZEND_TOSTRING_FUNC_NAME);
2127    } else if (name_len == sizeof(ZEND_DEBUGINFO_FUNC_NAME) - 1 &&
2128        !memcmp(lcname, ZEND_DEBUGINFO_FUNC_NAME, sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1) && fptr->common.num_args != 0) {
2129        zend_error(error_type, "Method %s::%s() cannot take arguments", ce->name->val, ZEND_DEBUGINFO_FUNC_NAME);
2130    }
2131}
2132/* }}} */
2133
2134/* registers all functions in *library_functions in the function hash */
2135ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC) /* {{{ */
2136{
2137    const zend_function_entry *ptr = functions;
2138    zend_function function, *reg_function;
2139    zend_internal_function *internal_function = (zend_internal_function *)&function;
2140    int count=0, unload=0;
2141    HashTable *target_function_table = function_table;
2142    int error_type;
2143    zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__callstatic = NULL, *__tostring = NULL, *__debugInfo = NULL;
2144    zend_string *lowercase_name;
2145    size_t fname_len;
2146    const char *lc_class_name = NULL;
2147    size_t class_name_len = 0;
2148
2149    if (type==MODULE_PERSISTENT) {
2150        error_type = E_CORE_WARNING;
2151    } else {
2152        error_type = E_WARNING;
2153    }
2154
2155    if (!target_function_table) {
2156        target_function_table = CG(function_table);
2157    }
2158    internal_function->type = ZEND_INTERNAL_FUNCTION;
2159    internal_function->module = EG(current_module);
2160
2161    if (scope) {
2162        class_name_len = scope->name->len;
2163        if ((lc_class_name = zend_memrchr(scope->name->val, '\\', class_name_len))) {
2164            ++lc_class_name;
2165            class_name_len -= (lc_class_name - scope->name->val);
2166            lc_class_name = zend_str_tolower_dup(lc_class_name, class_name_len);
2167        } else {
2168            lc_class_name = zend_str_tolower_dup(scope->name->val, class_name_len);
2169        }
2170    }
2171
2172    while (ptr->fname) {
2173        fname_len = strlen(ptr->fname);
2174        internal_function->handler = ptr->handler;
2175        internal_function->function_name = zend_new_interned_string(zend_string_init(ptr->fname, fname_len, 1) TSRMLS_CC);
2176        internal_function->scope = scope;
2177        internal_function->prototype = NULL;
2178        if (ptr->flags) {
2179            if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
2180                if (ptr->flags != ZEND_ACC_DEPRECATED || scope) {
2181                    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);
2182                }
2183                internal_function->fn_flags = ZEND_ACC_PUBLIC | ptr->flags;
2184            } else {
2185                internal_function->fn_flags = ptr->flags;
2186            }
2187        } else {
2188            internal_function->fn_flags = ZEND_ACC_PUBLIC;
2189        }
2190        if (ptr->arg_info) {
2191            zend_internal_function_info *info = (zend_internal_function_info*)ptr->arg_info;
2192
2193            internal_function->arg_info = (zend_arg_info*)ptr->arg_info+1;
2194            internal_function->num_args = ptr->num_args;
2195            /* Currently you cannot denote that the function can accept less arguments than num_args */
2196            if (info->required_num_args == -1) {
2197                internal_function->required_num_args = ptr->num_args;
2198            } else {
2199                internal_function->required_num_args = info->required_num_args;
2200            }
2201            if (info->return_reference) {
2202                internal_function->fn_flags |= ZEND_ACC_RETURN_REFERENCE;
2203            }
2204            if (ptr->arg_info[ptr->num_args].is_variadic) {
2205                internal_function->fn_flags |= ZEND_ACC_VARIADIC;
2206            }
2207        } else {
2208            internal_function->arg_info = NULL;
2209            internal_function->num_args = 0;
2210            internal_function->required_num_args = 0;
2211        }
2212        if (ptr->flags & ZEND_ACC_ABSTRACT) {
2213            if (scope) {
2214                /* This is a class that must be abstract itself. Here we set the check info. */
2215                scope->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
2216                if (!(scope->ce_flags & ZEND_ACC_INTERFACE)) {
2217                    /* Since the class is not an interface it needs to be declared as a abstract class. */
2218                    /* Since here we are handling internal functions only we can add the keyword flag. */
2219                    /* This time we set the flag for the keyword 'abstract'. */
2220                    scope->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
2221                }
2222            }
2223            if (ptr->flags & ZEND_ACC_STATIC && (!scope || !(scope->ce_flags & ZEND_ACC_INTERFACE))) {
2224                zend_error(error_type, "Static function %s%s%s() cannot be abstract", scope ? scope->name->val : "", scope ? "::" : "", ptr->fname);
2225            }
2226        } else {
2227            if (scope && (scope->ce_flags & ZEND_ACC_INTERFACE)) {
2228                efree((char*)lc_class_name);
2229                zend_error(error_type, "Interface %s cannot contain non abstract method %s()", scope->name->val, ptr->fname);
2230                return FAILURE;
2231            }
2232            if (!internal_function->handler) {
2233                if (scope) {
2234                    efree((char*)lc_class_name);
2235                }
2236                zend_error(error_type, "Method %s%s%s() cannot be a NULL function", scope ? scope->name->val : "", scope ? "::" : "", ptr->fname);
2237                zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
2238                return FAILURE;
2239            }
2240        }
2241        lowercase_name = zend_string_alloc(fname_len, 1);
2242        zend_str_tolower_copy(lowercase_name->val, ptr->fname, fname_len);
2243        lowercase_name = zend_new_interned_string(lowercase_name TSRMLS_CC);
2244        reg_function = malloc(sizeof(zend_internal_function));
2245        memcpy(reg_function, &function, sizeof(zend_internal_function));
2246        if (zend_hash_add_ptr(target_function_table, lowercase_name, reg_function) == NULL) {
2247            unload=1;
2248            free(reg_function);
2249            zend_string_release(lowercase_name);
2250            break;
2251        }
2252
2253        /* If types of arguments have to be checked */
2254        if (reg_function->common.arg_info && reg_function->common.num_args) {
2255            uint32_t i;
2256            for (i = 0; i < reg_function->common.num_args; i++) {
2257                if (reg_function->common.arg_info[i].class_name ||
2258                    reg_function->common.arg_info[i].type_hint) {
2259                    reg_function->common.fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
2260                    break;
2261                }
2262            }
2263        }
2264
2265        if (scope) {
2266            /* Look for ctor, dtor, clone
2267             * If it's an old-style constructor, store it only if we don't have
2268             * a constructor already.
2269             */
2270            if ((fname_len == class_name_len) && !ctor && !memcmp(lowercase_name->val, lc_class_name, class_name_len+1)) {
2271                ctor = reg_function;
2272            } else if (zend_string_equals_literal(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME)) {
2273                ctor = reg_function;
2274            } else if (zend_string_equals_literal(lowercase_name, ZEND_DESTRUCTOR_FUNC_NAME)) {
2275                dtor = reg_function;
2276                if (internal_function->num_args) {
2277                    zend_error(error_type, "Destructor %s::%s() cannot take arguments", scope->name->val, ptr->fname);
2278                }
2279            } else if (zend_string_equals_literal(lowercase_name, ZEND_CLONE_FUNC_NAME)) {
2280                clone = reg_function;
2281            } else if (zend_string_equals_literal(lowercase_name, ZEND_CALL_FUNC_NAME)) {
2282                __call = reg_function;
2283            } else if (zend_string_equals_literal(lowercase_name, ZEND_CALLSTATIC_FUNC_NAME)) {
2284                __callstatic = reg_function;
2285            } else if (zend_string_equals_literal(lowercase_name, ZEND_TOSTRING_FUNC_NAME)) {
2286                __tostring = reg_function;
2287            } else if (zend_string_equals_literal(lowercase_name, ZEND_GET_FUNC_NAME)) {
2288                __get = reg_function;
2289            } else if (zend_string_equals_literal(lowercase_name, ZEND_SET_FUNC_NAME)) {
2290                __set = reg_function;
2291            } else if (zend_string_equals_literal(lowercase_name, ZEND_UNSET_FUNC_NAME)) {
2292                __unset = reg_function;
2293            } else if (zend_string_equals_literal(lowercase_name, ZEND_ISSET_FUNC_NAME)) {
2294                __isset = reg_function;
2295            } else if (zend_string_equals_literal(lowercase_name, ZEND_DEBUGINFO_FUNC_NAME)) {
2296                __debugInfo = reg_function;
2297            } else {
2298                reg_function = NULL;
2299            }
2300            if (reg_function) {
2301                zend_check_magic_method_implementation(scope, reg_function, error_type TSRMLS_CC);
2302            }
2303        }
2304        ptr++;
2305        count++;
2306        zend_string_release(lowercase_name);
2307    }
2308    if (unload) { /* before unloading, display all remaining bad function in the module */
2309        if (scope) {
2310            efree((char*)lc_class_name);
2311        }
2312        while (ptr->fname) {
2313            fname_len = strlen(ptr->fname);
2314            lowercase_name = zend_string_alloc(fname_len, 0);
2315            zend_str_tolower_copy(lowercase_name->val, ptr->fname, fname_len);
2316            if (zend_hash_exists(target_function_table, lowercase_name)) {
2317                zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? scope->name->val : "", scope ? "::" : "", ptr->fname);
2318            }
2319            zend_string_free(lowercase_name);
2320            ptr++;
2321        }
2322        zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
2323        return FAILURE;
2324    }
2325    if (scope) {
2326        scope->constructor = ctor;
2327        scope->destructor = dtor;
2328        scope->clone = clone;
2329        scope->__call = __call;
2330        scope->__callstatic = __callstatic;
2331        scope->__tostring = __tostring;
2332        scope->__get = __get;
2333        scope->__set = __set;
2334        scope->__unset = __unset;
2335        scope->__isset = __isset;
2336        scope->__debugInfo = __debugInfo;
2337        if (ctor) {
2338            ctor->common.fn_flags |= ZEND_ACC_CTOR;
2339            if (ctor->common.fn_flags & ZEND_ACC_STATIC) {
2340                zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name->val, ctor->common.function_name->val);
2341            }
2342            ctor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2343        }
2344        if (dtor) {
2345            dtor->common.fn_flags |= ZEND_ACC_DTOR;
2346            if (dtor->common.fn_flags & ZEND_ACC_STATIC) {
2347                zend_error(error_type, "Destructor %s::%s() cannot be static", scope->name->val, dtor->common.function_name->val);
2348            }
2349            dtor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2350        }
2351        if (clone) {
2352            clone->common.fn_flags |= ZEND_ACC_CLONE;
2353            if (clone->common.fn_flags & ZEND_ACC_STATIC) {
2354                zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name->val, clone->common.function_name->val);
2355            }
2356            clone->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2357        }
2358        if (__call) {
2359            if (__call->common.fn_flags & ZEND_ACC_STATIC) {
2360                zend_error(error_type, "Method %s::%s() cannot be static", scope->name->val, __call->common.function_name->val);
2361            }
2362            __call->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2363        }
2364        if (__callstatic) {
2365            if (!(__callstatic->common.fn_flags & ZEND_ACC_STATIC)) {
2366                zend_error(error_type, "Method %s::%s() must be static", scope->name->val, __callstatic->common.function_name->val);
2367            }
2368            __callstatic->common.fn_flags |= ZEND_ACC_STATIC;
2369        }
2370        if (__tostring) {
2371            if (__tostring->common.fn_flags & ZEND_ACC_STATIC) {
2372                zend_error(error_type, "Method %s::%s() cannot be static", scope->name->val, __tostring->common.function_name->val);
2373            }
2374            __tostring->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2375        }
2376        if (__get) {
2377            if (__get->common.fn_flags & ZEND_ACC_STATIC) {
2378                zend_error(error_type, "Method %s::%s() cannot be static", scope->name->val, __get->common.function_name->val);
2379            }
2380            __get->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2381        }
2382        if (__set) {
2383            if (__set->common.fn_flags & ZEND_ACC_STATIC) {
2384                zend_error(error_type, "Method %s::%s() cannot be static", scope->name->val, __set->common.function_name->val);
2385            }
2386            __set->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2387        }
2388        if (__unset) {
2389            if (__unset->common.fn_flags & ZEND_ACC_STATIC) {
2390                zend_error(error_type, "Method %s::%s() cannot be static", scope->name->val, __unset->common.function_name->val);
2391            }
2392            __unset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2393        }
2394        if (__isset) {
2395            if (__isset->common.fn_flags & ZEND_ACC_STATIC) {
2396                zend_error(error_type, "Method %s::%s() cannot be static", scope->name->val, __isset->common.function_name->val);
2397            }
2398            __isset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2399        }
2400        if (__debugInfo) {
2401            if (__debugInfo->common.fn_flags & ZEND_ACC_STATIC) {
2402                zend_error(error_type, "Method %s::%s() cannot be static", scope->name->val, __debugInfo->common.function_name->val);
2403            }
2404        }
2405        efree((char*)lc_class_name);
2406    }
2407    return SUCCESS;
2408}
2409/* }}} */
2410
2411/* count=-1 means erase all functions, otherwise,
2412 * erase the first count functions
2413 */
2414ZEND_API void zend_unregister_functions(const zend_function_entry *functions, int count, HashTable *function_table TSRMLS_DC) /* {{{ */
2415{
2416    const zend_function_entry *ptr = functions;
2417    int i=0;
2418    HashTable *target_function_table = function_table;
2419    zend_string *lowercase_name;
2420    size_t fname_len;
2421
2422    if (!target_function_table) {
2423        target_function_table = CG(function_table);
2424    }
2425    while (ptr->fname) {
2426        if (count!=-1 && i>=count) {
2427            break;
2428        }
2429        fname_len = strlen(ptr->fname);
2430        lowercase_name = zend_string_alloc(fname_len, 0);
2431        zend_str_tolower_copy(lowercase_name->val, ptr->fname, fname_len);
2432        zend_hash_del(target_function_table, lowercase_name);
2433        zend_string_free(lowercase_name);
2434        ptr++;
2435        i++;
2436    }
2437}
2438/* }}} */
2439
2440ZEND_API int zend_startup_module(zend_module_entry *module TSRMLS_DC) /* {{{ */
2441{
2442    if ((module = zend_register_internal_module(module TSRMLS_CC)) != NULL && zend_startup_module_ex(module TSRMLS_CC) == SUCCESS) {
2443        return SUCCESS;
2444    }
2445    return FAILURE;
2446}
2447/* }}} */
2448
2449ZEND_API int zend_get_module_started(const char *module_name) /* {{{ */
2450{
2451    zend_module_entry *module;
2452
2453    module = zend_hash_str_find_ptr(&module_registry, module_name, strlen(module_name));
2454    return (module && module->module_started) ? SUCCESS : FAILURE;
2455}
2456/* }}} */
2457
2458static int clean_module_class(zval *el, void *arg TSRMLS_DC) /* {{{ */
2459{
2460    zend_class_entry *ce = (zend_class_entry *)Z_PTR_P(el);
2461    int module_number = *(int *)arg;
2462    if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module->module_number == module_number) {
2463        return ZEND_HASH_APPLY_REMOVE;
2464    } else {
2465        return ZEND_HASH_APPLY_KEEP;
2466    }
2467}
2468/* }}} */
2469
2470static void clean_module_classes(int module_number TSRMLS_DC) /* {{{ */
2471{
2472    zend_hash_apply_with_argument(EG(class_table), clean_module_class, (void *) &module_number TSRMLS_CC);
2473}
2474/* }}} */
2475
2476void module_destructor(zend_module_entry *module) /* {{{ */
2477{
2478    TSRMLS_FETCH();
2479
2480    if (module->type == MODULE_TEMPORARY) {
2481        zend_clean_module_rsrc_dtors(module->module_number TSRMLS_CC);
2482        clean_module_constants(module->module_number TSRMLS_CC);
2483        clean_module_classes(module->module_number TSRMLS_CC);
2484    }
2485
2486    if (module->module_started && module->module_shutdown_func) {
2487#if 0
2488        zend_printf("%s: Module shutdown\n", module->name);
2489#endif
2490        module->module_shutdown_func(module->type, module->module_number TSRMLS_CC);
2491    }
2492
2493    /* Deinitilaise module globals */
2494    if (module->globals_size) {
2495#ifdef ZTS
2496        if (*module->globals_id_ptr) {
2497            ts_free_id(*module->globals_id_ptr);
2498        }
2499#else
2500        if (module->globals_dtor) {
2501            module->globals_dtor(module->globals_ptr TSRMLS_CC);
2502        }
2503#endif
2504    }
2505
2506    module->module_started=0;
2507    if (module->functions) {
2508        zend_unregister_functions(module->functions, -1, NULL TSRMLS_CC);
2509    }
2510
2511#if HAVE_LIBDL
2512#if !(defined(NETWARE) && defined(APACHE_1_BUILD))
2513    if (module->handle && !getenv("ZEND_DONT_UNLOAD_MODULES")) {
2514        DL_UNLOAD(module->handle);
2515    }
2516#endif
2517#endif
2518}
2519/* }}} */
2520
2521ZEND_API void zend_activate_modules(TSRMLS_D) /* {{{ */
2522{
2523    zend_module_entry **p = module_request_startup_handlers;
2524
2525    while (*p) {
2526        zend_module_entry *module = *p;
2527
2528        if (module->request_startup_func(module->type, module->module_number TSRMLS_CC)==FAILURE) {
2529            zend_error(E_WARNING, "request_startup() for %s module failed", module->name);
2530            exit(1);
2531        }
2532        p++;
2533    }
2534}
2535/* }}} */
2536
2537/* call request shutdown for all modules */
2538static int module_registry_cleanup(zval *zv TSRMLS_DC) /* {{{ */
2539{
2540    zend_module_entry *module = Z_PTR_P(zv);
2541
2542    if (module->request_shutdown_func) {
2543#if 0
2544        zend_printf("%s: Request shutdown\n", module->name);
2545#endif
2546        module->request_shutdown_func(module->type, module->module_number TSRMLS_CC);
2547    }
2548    return 0;
2549}
2550/* }}} */
2551
2552ZEND_API void zend_deactivate_modules(TSRMLS_D) /* {{{ */
2553{
2554    EG(current_execute_data) = NULL; /* we're no longer executing anything */
2555
2556    zend_try {
2557        if (EG(full_tables_cleanup)) {
2558            zend_hash_reverse_apply(&module_registry, module_registry_cleanup TSRMLS_CC);
2559        } else {
2560            zend_module_entry **p = module_request_shutdown_handlers;
2561
2562            while (*p) {
2563                zend_module_entry *module = *p;
2564
2565                module->request_shutdown_func(module->type, module->module_number TSRMLS_CC);
2566                p++;
2567            }
2568        }
2569    } zend_end_try();
2570}
2571/* }}} */
2572
2573ZEND_API void zend_cleanup_internal_classes(TSRMLS_D) /* {{{ */
2574{
2575    zend_class_entry **p = class_cleanup_handlers;
2576
2577    while (*p) {
2578        zend_cleanup_internal_class_data(*p TSRMLS_CC);
2579        p++;
2580    }
2581}
2582/* }}} */
2583
2584int module_registry_unload_temp(const zend_module_entry *module TSRMLS_DC) /* {{{ */
2585{
2586    return (module->type == MODULE_TEMPORARY) ? ZEND_HASH_APPLY_REMOVE : ZEND_HASH_APPLY_STOP;
2587}
2588/* }}} */
2589
2590static int module_registry_unload_temp_wrapper(zval *el TSRMLS_DC) /* {{{ */
2591{
2592    zend_module_entry *module = (zend_module_entry *)Z_PTR_P(el);
2593    return module_registry_unload_temp((const zend_module_entry *)module TSRMLS_CC);
2594}
2595/* }}} */
2596
2597static int exec_done_cb(zval *el TSRMLS_DC) /* {{{ */
2598{
2599    zend_module_entry *module = (zend_module_entry *)Z_PTR_P(el);
2600    if (module->post_deactivate_func) {
2601        module->post_deactivate_func();
2602    }
2603    return 0;
2604}
2605/* }}} */
2606
2607ZEND_API void zend_post_deactivate_modules(TSRMLS_D) /* {{{ */
2608{
2609    if (EG(full_tables_cleanup)) {
2610        zend_hash_apply(&module_registry, exec_done_cb TSRMLS_CC);
2611        zend_hash_reverse_apply(&module_registry, module_registry_unload_temp_wrapper TSRMLS_CC);
2612    } else {
2613        zend_module_entry **p = module_post_deactivate_handlers;
2614
2615        while (*p) {
2616            zend_module_entry *module = *p;
2617
2618            module->post_deactivate_func();
2619            p++;
2620        }
2621    }
2622}
2623/* }}} */
2624
2625/* return the next free module number */
2626ZEND_API int zend_next_free_module(void) /* {{{ */
2627{
2628    return zend_hash_num_elements(&module_registry) + 1;
2629}
2630/* }}} */
2631
2632static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, uint32_t ce_flags TSRMLS_DC) /* {{{ */
2633{
2634    zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
2635    zend_string *lowercase_name = zend_string_alloc(orig_class_entry->name->len, 1);
2636    *class_entry = *orig_class_entry;
2637
2638    class_entry->type = ZEND_INTERNAL_CLASS;
2639    zend_initialize_class_data(class_entry, 0 TSRMLS_CC);
2640    class_entry->ce_flags = ce_flags | ZEND_ACC_CONSTANTS_UPDATED;
2641    class_entry->info.internal.module = EG(current_module);
2642
2643    if (class_entry->info.internal.builtin_functions) {
2644        zend_register_functions(class_entry, class_entry->info.internal.builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC);
2645    }
2646
2647    zend_str_tolower_copy(lowercase_name->val, orig_class_entry->name->val, class_entry->name->len);
2648    lowercase_name = zend_new_interned_string(lowercase_name TSRMLS_CC);
2649    zend_hash_update_ptr(CG(class_table), lowercase_name, class_entry);
2650    zend_string_release(lowercase_name);
2651    return class_entry;
2652}
2653/* }}} */
2654
2655/* If parent_ce is not NULL then it inherits from parent_ce
2656 * If parent_ce is NULL and parent_name isn't then it looks for the parent and inherits from it
2657 * If both parent_ce and parent_name are NULL it does a regular class registration
2658 * If parent_name is specified but not found NULL is returned
2659 */
2660ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce TSRMLS_DC) /* {{{ */
2661{
2662    zend_class_entry *register_class;
2663
2664    register_class = zend_register_internal_class(class_entry TSRMLS_CC);
2665
2666    if (parent_ce) {
2667        zend_do_inheritance(register_class, parent_ce TSRMLS_CC);
2668    }
2669    return register_class;
2670}
2671/* }}} */
2672
2673ZEND_API void zend_class_implements(zend_class_entry *class_entry TSRMLS_DC, int num_interfaces, ...) /* {{{ */
2674{
2675    zend_class_entry *interface_entry;
2676    va_list interface_list;
2677    va_start(interface_list, num_interfaces);
2678
2679    while (num_interfaces--) {
2680        interface_entry = va_arg(interface_list, zend_class_entry *);
2681        zend_do_implement_interface(class_entry, interface_entry TSRMLS_CC);
2682    }
2683
2684    va_end(interface_list);
2685}
2686/* }}} */
2687
2688/* A class that contains at least one abstract method automatically becomes an abstract class.
2689 */
2690ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry TSRMLS_DC) /* {{{ */
2691{
2692    return do_register_internal_class(orig_class_entry, 0 TSRMLS_CC);
2693}
2694/* }}} */
2695
2696ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry TSRMLS_DC) /* {{{ */
2697{
2698    return do_register_internal_class(orig_class_entry, ZEND_ACC_INTERFACE TSRMLS_CC);
2699}
2700/* }}} */
2701
2702ZEND_API int zend_register_class_alias_ex(const char *name, size_t name_len, zend_class_entry *ce TSRMLS_DC) /* {{{ */
2703{
2704    zend_string *lcname;
2705
2706    if (name[0] == '\\') {
2707        lcname = zend_string_alloc(name_len-1, 1);
2708        zend_str_tolower_copy(lcname->val, name+1, name_len-1);
2709    } else {
2710        lcname = zend_string_alloc(name_len, 1);
2711        zend_str_tolower_copy(lcname->val, name, name_len);
2712    }
2713    ce = zend_hash_add_ptr(CG(class_table), lcname, ce);
2714    zend_string_release(lcname);
2715    if (ce) {
2716        ce->refcount++;
2717        return SUCCESS;
2718    }
2719    return FAILURE;
2720}
2721/* }}} */
2722
2723ZEND_API int zend_set_hash_symbol(zval *symbol, const char *name, int name_length, zend_bool is_ref, int num_symbol_tables, ...) /* {{{ */
2724{
2725    HashTable *symbol_table;
2726    va_list symbol_table_list;
2727
2728    if (num_symbol_tables <= 0) return FAILURE;
2729
2730    if (is_ref) {
2731        ZVAL_MAKE_REF(symbol);
2732    }
2733
2734    va_start(symbol_table_list, num_symbol_tables);
2735    while (num_symbol_tables-- > 0) {
2736        symbol_table = va_arg(symbol_table_list, HashTable *);
2737        zend_hash_str_update(symbol_table, name, name_length, symbol);
2738        if (Z_REFCOUNTED_P(symbol)) {
2739            Z_ADDREF_P(symbol);
2740        }
2741    }
2742    va_end(symbol_table_list);
2743    return SUCCESS;
2744}
2745/* }}} */
2746
2747/* Disabled functions support */
2748
2749/* {{{ proto void display_disabled_function(void)
2750Dummy function which displays an error when a disabled function is called. */
2751ZEND_API ZEND_FUNCTION(display_disabled_function)
2752{
2753    zend_error(E_WARNING, "%s() has been disabled for security reasons", get_active_function_name(TSRMLS_C));
2754}
2755/* }}} */
2756
2757ZEND_API int zend_disable_function(char *function_name, size_t function_name_length TSRMLS_DC) /* {{{ */
2758{
2759    zend_internal_function *func;
2760    if ((func = zend_hash_str_find_ptr(CG(function_table), function_name, function_name_length))) {
2761        func->arg_info = NULL;
2762        func->handler = ZEND_FN(display_disabled_function);
2763        return SUCCESS;
2764    }
2765    return FAILURE;
2766}
2767/* }}} */
2768
2769#ifdef ZEND_WIN32
2770#pragma optimize("", off)
2771#endif
2772static zend_object *display_disabled_class(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
2773{
2774    zend_object *intern;
2775
2776    intern = zend_objects_new(class_type TSRMLS_CC);
2777    zend_error(E_WARNING, "%s() has been disabled for security reasons", class_type->name->val);
2778    return intern;
2779}
2780#ifdef ZEND_WIN32
2781#pragma optimize("", on)
2782#endif
2783/* }}} */
2784
2785static const zend_function_entry disabled_class_new[] = {
2786    ZEND_FE_END
2787};
2788
2789ZEND_API int zend_disable_class(char *class_name, size_t class_name_length TSRMLS_DC) /* {{{ */
2790{
2791    zend_class_entry *disabled_class;
2792    zend_string *key;
2793
2794    key = zend_string_alloc(class_name_length, 0);
2795    zend_str_tolower_copy(key->val, class_name, class_name_length);
2796    disabled_class = zend_hash_find_ptr(CG(class_table), key);
2797    if (!disabled_class) {
2798        return FAILURE;
2799    }
2800    INIT_CLASS_ENTRY_INIT_METHODS((*disabled_class), disabled_class_new, NULL, NULL, NULL, NULL, NULL);
2801    disabled_class->create_object = display_disabled_class;
2802    zend_hash_clean(&disabled_class->function_table);
2803    return SUCCESS;
2804}
2805/* }}} */
2806
2807static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache *fcc, int *strict_class, char **error TSRMLS_DC) /* {{{ */
2808{
2809    int ret = 0;
2810    zend_class_entry *ce;
2811    size_t name_len = name->len;
2812    zend_string *lcname;
2813    ALLOCA_FLAG(use_heap);
2814
2815    STR_ALLOCA_ALLOC(lcname, name_len, use_heap);
2816    zend_str_tolower_copy(lcname->val, name->val, name_len);
2817
2818    *strict_class = 0;
2819    if (zend_string_equals_literal(lcname, "self")) {
2820        if (!EG(scope)) {
2821            if (error) *error = estrdup("cannot access self:: when no class scope is active");
2822        } else {
2823            fcc->called_scope = EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL;
2824            fcc->calling_scope = EG(scope);
2825            if (!fcc->object && EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This)) {
2826                fcc->object = Z_OBJ(EG(current_execute_data)->This);
2827            }
2828            ret = 1;
2829        }
2830    } else if (zend_string_equals_literal(lcname, "parent")) {
2831        if (!EG(scope)) {
2832            if (error) *error = estrdup("cannot access parent:: when no class scope is active");
2833        } else if (!EG(scope)->parent) {
2834            if (error) *error = estrdup("cannot access parent:: when current class scope has no parent");
2835        } else {
2836            fcc->called_scope = EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL;
2837            fcc->calling_scope = EG(scope)->parent;
2838            if (!fcc->object && EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This)) {
2839                fcc->object = Z_OBJ(EG(current_execute_data)->This);
2840            }
2841            *strict_class = 1;
2842            ret = 1;
2843        }
2844    } else if (zend_string_equals_literal(lcname, "static")) {
2845        if (!EG(current_execute_data) || !EG(current_execute_data)->called_scope) {
2846            if (error) *error = estrdup("cannot access static:: when no class scope is active");
2847        } else {
2848            fcc->called_scope = EG(current_execute_data)->called_scope;
2849            fcc->calling_scope = EG(current_execute_data)->called_scope;
2850            if (!fcc->object && Z_OBJ(EG(current_execute_data)->This)) {
2851                fcc->object = Z_OBJ(EG(current_execute_data)->This);
2852            }
2853            *strict_class = 1;
2854            ret = 1;
2855        }
2856    } else if ((ce = zend_lookup_class_ex(name, NULL, 1 TSRMLS_CC)) != NULL) {
2857        zend_class_entry *scope;
2858        zend_execute_data *ex = EG(current_execute_data);
2859
2860        while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
2861            ex = ex->prev_execute_data;
2862        }
2863        scope = ex ? ex->func->common.scope : NULL;
2864        fcc->calling_scope = ce;
2865        if (scope && !fcc->object && EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This) &&
2866            instanceof_function(Z_OBJCE(EG(current_execute_data)->This), scope TSRMLS_CC) &&
2867            instanceof_function(scope, fcc->calling_scope TSRMLS_CC)) {
2868            fcc->object = Z_OBJ(EG(current_execute_data)->This);
2869            fcc->called_scope = Z_OBJCE(EG(current_execute_data)->This);
2870        } else {
2871            fcc->called_scope = fcc->object ? fcc->object->ce : fcc->calling_scope;
2872        }
2873        *strict_class = 1;
2874        ret = 1;
2875    } else {
2876        if (error) zend_spprintf(error, 0, "class '%.*s' not found", name_len, name->val);
2877    }
2878    STR_ALLOCA_FREE(lcname, use_heap);
2879    return ret;
2880}
2881/* }}} */
2882
2883static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fcall_info_cache *fcc, int strict_class, char **error TSRMLS_DC) /* {{{ */
2884{
2885    zend_class_entry *ce_org = fcc->calling_scope;
2886    int retval = 0;
2887    zend_string *mname, *cname;
2888    zend_string *lmname;
2889    const char *colon;
2890    size_t clen, mlen;
2891    zend_class_entry *last_scope;
2892    HashTable *ftable;
2893    int call_via_handler = 0;
2894    ALLOCA_FLAG(use_heap)
2895
2896    if (error) {
2897        *error = NULL;
2898    }
2899
2900    fcc->calling_scope = NULL;
2901    fcc->function_handler = NULL;
2902
2903    if (!ce_org) {
2904        zend_string *lmname;
2905
2906        /* Skip leading \ */
2907        if (UNEXPECTED(Z_STRVAL_P(callable)[0] == '\\')) {
2908            STR_ALLOCA_INIT(lmname, Z_STRVAL_P(callable) + 1, Z_STRLEN_P(callable) - 1, use_heap);
2909        } else {
2910            lmname = Z_STR_P(callable);
2911        }
2912        /* Check if function with given name exists.
2913         * This may be a compound name that includes namespace name */
2914        if (EXPECTED((fcc->function_handler = zend_hash_find_ptr(EG(function_table), lmname)) != NULL)) {
2915            if (lmname != Z_STR_P(callable)) {
2916                STR_ALLOCA_FREE(lmname, use_heap);
2917            }
2918            return 1;
2919        } else {
2920            if (lmname == Z_STR_P(callable)) {
2921                STR_ALLOCA_INIT(lmname, Z_STRVAL_P(callable), Z_STRLEN_P(callable), use_heap);
2922            } else {
2923                zend_string_forget_hash_val(lmname);
2924            }
2925            zend_str_tolower(lmname->val, lmname->len);
2926            if ((fcc->function_handler = zend_hash_find_ptr(EG(function_table), lmname)) != NULL) {
2927                STR_ALLOCA_FREE(lmname, use_heap);
2928                return 1;
2929            }
2930        }
2931        if (lmname != Z_STR_P(callable)) {
2932            STR_ALLOCA_FREE(lmname, use_heap);
2933        }
2934    }
2935
2936    /* Split name into class/namespace and method/function names */
2937    if ((colon = zend_memrchr(Z_STRVAL_P(callable), ':', Z_STRLEN_P(callable))) != NULL &&
2938        colon > Z_STRVAL_P(callable) &&
2939        *(colon-1) == ':'
2940    ) {
2941        colon--;
2942        clen = colon - Z_STRVAL_P(callable);
2943        mlen = Z_STRLEN_P(callable) - clen - 2;
2944
2945        if (colon == Z_STRVAL_P(callable)) {
2946            if (error) zend_spprintf(error, 0, "invalid function name");
2947            return 0;
2948        }
2949
2950        /* This is a compound name.
2951         * Try to fetch class and then find static method. */
2952        last_scope = EG(scope);
2953        if (ce_org) {
2954            EG(scope) = ce_org;
2955        }
2956
2957        cname = zend_string_init(Z_STRVAL_P(callable), clen, 0);
2958        if (!zend_is_callable_check_class(cname, fcc, &strict_class, error TSRMLS_CC)) {
2959            zend_string_release(cname);
2960            EG(scope) = last_scope;
2961            return 0;
2962        }
2963        zend_string_release(cname);
2964        EG(scope) = last_scope;
2965
2966        ftable = &fcc->calling_scope->function_table;
2967        if (ce_org && !instanceof_function(ce_org, fcc->calling_scope TSRMLS_CC)) {
2968            if (error) zend_spprintf(error, 0, "class '%s' is not a subclass of '%s'", ce_org->name->val, fcc->calling_scope->name->val);
2969            return 0;
2970        }
2971        mname = zend_string_init(Z_STRVAL_P(callable) + clen + 2, mlen, 0);
2972    } else if (ce_org) {
2973        /* Try to fetch find static method of given class. */
2974        mlen = Z_STRLEN_P(callable);
2975        mname = Z_STR_P(callable);
2976        zend_string_addref(mname);
2977        ftable = &ce_org->function_table;
2978        fcc->calling_scope = ce_org;
2979    } else {
2980        /* We already checked for plain function before. */
2981        if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) {
2982            zend_spprintf(error, 0, "function '%s' not found or invalid function name", Z_STRVAL_P(callable));
2983        }
2984        return 0;
2985    }
2986
2987    lmname = zend_string_alloc(mlen, 0);
2988    zend_str_tolower_copy(lmname->val, mname->val, mlen);
2989    if (strict_class &&
2990        fcc->calling_scope &&
2991        zend_string_equals_literal(lmname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
2992        fcc->function_handler = fcc->calling_scope->constructor;
2993        if (fcc->function_handler) {
2994            retval = 1;
2995        }
2996    } else if ((fcc->function_handler = zend_hash_find_ptr(ftable, lmname)) != NULL) {
2997        retval = 1;
2998        if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) &&
2999            !strict_class && EG(scope) &&
3000            instanceof_function(fcc->function_handler->common.scope, EG(scope) TSRMLS_CC)) {
3001            zend_function *priv_fbc;
3002
3003            if ((priv_fbc = zend_hash_find_ptr(&EG(scope)->function_table, lmname)) != NULL
3004                && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE
3005                && priv_fbc->common.scope == EG(scope)) {
3006                fcc->function_handler = priv_fbc;
3007            }
3008        }
3009        if ((check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0 &&
3010            (fcc->calling_scope &&
3011             ((fcc->object && fcc->calling_scope->__call) ||
3012              (!fcc->object && fcc->calling_scope->__callstatic)))) {
3013            if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
3014                if (!zend_check_private(fcc->function_handler, fcc->object ? fcc->object->ce : EG(scope), lmname TSRMLS_CC)) {
3015                    retval = 0;
3016                    fcc->function_handler = NULL;
3017                    goto get_function_via_handler;
3018                }
3019            } else if (fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED) {
3020                if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) {
3021                    retval = 0;
3022                    fcc->function_handler = NULL;
3023                    goto get_function_via_handler;
3024                }
3025            }
3026        }
3027    } else {
3028get_function_via_handler:
3029        if (fcc->object && fcc->calling_scope == ce_org) {
3030            if (strict_class && ce_org->__call) {
3031                fcc->function_handler = emalloc(sizeof(zend_internal_function));
3032                fcc->function_handler->internal_function.type = ZEND_INTERNAL_FUNCTION;
3033                fcc->function_handler->internal_function.module = (ce_org->type == ZEND_INTERNAL_CLASS) ? ce_org->info.internal.module : NULL;
3034                fcc->function_handler->internal_function.handler = zend_std_call_user_call;
3035                fcc->function_handler->internal_function.arg_info = NULL;
3036                fcc->function_handler->internal_function.num_args = 0;
3037                fcc->function_handler->internal_function.scope = ce_org;
3038                fcc->function_handler->internal_function.fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
3039                fcc->function_handler->internal_function.function_name = mname;
3040                zend_string_addref(mname);
3041                call_via_handler = 1;
3042                retval = 1;
3043            } else if (fcc->object->handlers->get_method) {
3044                fcc->function_handler = fcc->object->handlers->get_method(&fcc->object, mname, NULL TSRMLS_CC);
3045                if (fcc->function_handler) {
3046                    if (strict_class &&
3047                        (!fcc->function_handler->common.scope ||
3048                         !instanceof_function(ce_org, fcc->function_handler->common.scope TSRMLS_CC))) {
3049                        if ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0) {
3050                            if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
3051                                zend_string_release(fcc->function_handler->common.function_name);
3052                            }
3053                            efree(fcc->function_handler);
3054                        }
3055                    } else {
3056                        retval = 1;
3057                        call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
3058                    }
3059                }
3060            }
3061        } else if (fcc->calling_scope) {
3062            if (fcc->calling_scope->get_static_method) {
3063                fcc->function_handler = fcc->calling_scope->get_static_method(fcc->calling_scope, mname TSRMLS_CC);
3064            } else {
3065                fcc->function_handler = zend_std_get_static_method(fcc->calling_scope, mname, NULL TSRMLS_CC);
3066            }
3067            if (fcc->function_handler) {
3068                retval = 1;
3069                call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
3070                if (call_via_handler && !fcc->object && EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This) &&
3071                    instanceof_function(Z_OBJCE(EG(current_execute_data)->This), fcc->calling_scope TSRMLS_CC)) {
3072                    fcc->object = Z_OBJ(EG(current_execute_data)->This);
3073                }
3074            }
3075        }
3076    }
3077
3078    if (retval) {
3079        if (fcc->calling_scope && !call_via_handler) {
3080            if (!fcc->object && (fcc->function_handler->common.fn_flags & ZEND_ACC_ABSTRACT)) {
3081                if (error) {
3082                    zend_spprintf(error, 0, "cannot call abstract method %s::%s()", fcc->calling_scope->name->val, fcc->function_handler->common.function_name->val);
3083                    retval = 0;
3084                } else {
3085                    zend_error(E_ERROR, "Cannot call abstract method %s::%s()", fcc->calling_scope->name->val, fcc->function_handler->common.function_name->val);
3086                }
3087            } else if (!fcc->object && !(fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) {
3088                int severity;
3089                char *verb;
3090                if (fcc->function_handler->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
3091                    severity = E_STRICT;
3092                    verb = "should not";
3093                } else {
3094                    /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
3095                    severity = E_ERROR;
3096                    verb = "cannot";
3097                }
3098                if ((check_flags & IS_CALLABLE_CHECK_IS_STATIC) != 0) {
3099                    retval = 0;
3100                }
3101                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)) {
3102                    fcc->object = Z_OBJ(EG(current_execute_data)->This);
3103                    if (error) {
3104                        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);
3105                        if (severity == E_ERROR) {
3106                            retval = 0;
3107                        }
3108                    } else if (retval) {
3109                        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);
3110                    }
3111                } else {
3112                    if (error) {
3113                        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);
3114                        if (severity == E_ERROR) {
3115                            retval = 0;
3116                        }
3117                    } else if (retval) {
3118                        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);
3119                    }
3120                }
3121            }
3122            if (retval && (check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0) {
3123                if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
3124                    if (!zend_check_private(fcc->function_handler, fcc->object ? fcc->object->ce : EG(scope), lmname TSRMLS_CC)) {
3125                        if (error) {
3126                            if (*error) {
3127                                efree(*error);
3128                            }
3129                            zend_spprintf(error, 0, "cannot access private method %s::%s()", fcc->calling_scope->name->val, fcc->function_handler->common.function_name->val);
3130                        }
3131                        retval = 0;
3132                    }
3133                } else if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED)) {
3134                    if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) {
3135                        if (error) {
3136                            if (*error) {
3137                                efree(*error);
3138                            }
3139                            zend_spprintf(error, 0, "cannot access protected method %s::%s()", fcc->calling_scope->name->val, fcc->function_handler->common.function_name->val);
3140                        }
3141                        retval = 0;
3142                    }
3143                }
3144            }
3145        }
3146    } else if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) {
3147        if (fcc->calling_scope) {
3148            if (error) zend_spprintf(error, 0, "class '%s' does not have a method '%s'", fcc->calling_scope->name->val, mname->val);
3149        } else {
3150            if (error) zend_spprintf(error, 0, "function '%s' does not exist", mname->val);
3151        }
3152    }
3153    zend_string_free(lmname);
3154    zend_string_release(mname);
3155
3156    if (fcc->object) {
3157        fcc->called_scope = fcc->object->ce;
3158    }
3159    if (retval) {
3160        fcc->initialized = 1;
3161    }
3162    return retval;
3163}
3164/* }}} */
3165
3166ZEND_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) /* {{{ */
3167{
3168    zend_bool ret;
3169    zend_fcall_info_cache fcc_local;
3170
3171    if (callable_name) {
3172        *callable_name = NULL;
3173    }
3174    if (fcc == NULL) {
3175        fcc = &fcc_local;
3176    }
3177    if (error) {
3178        *error = NULL;
3179    }
3180
3181    fcc->initialized = 0;
3182    fcc->calling_scope = NULL;
3183    fcc->called_scope = NULL;
3184    fcc->function_handler = NULL;
3185    fcc->calling_scope = NULL;
3186    fcc->object = NULL;
3187
3188    if (object &&
3189        (!EG(objects_store).object_buckets ||
3190         !IS_OBJ_VALID(EG(objects_store).object_buckets[object->handle]))) {
3191        return 0;
3192    }
3193
3194    switch (Z_TYPE_P(callable)) {
3195        case IS_STRING:
3196            if (object) {
3197                fcc->object = object;
3198                fcc->calling_scope = object->ce;
3199                if (callable_name) {
3200                    char *ptr;
3201
3202                    *callable_name = zend_string_alloc(fcc->calling_scope->name->len + Z_STRLEN_P(callable) + sizeof("::") - 1, 0);
3203                    ptr = (*callable_name)->val;
3204                    memcpy(ptr, fcc->calling_scope->name->val, fcc->calling_scope->name->len);
3205                    ptr += fcc->calling_scope->name->len;
3206                    memcpy(ptr, "::", sizeof("::") - 1);
3207                    ptr += sizeof("::") - 1;
3208                    memcpy(ptr, Z_STRVAL_P(callable), Z_STRLEN_P(callable) + 1);
3209                }
3210            } else if (callable_name) {
3211                *callable_name = zend_string_copy(Z_STR_P(callable));
3212            }
3213            if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3214                fcc->called_scope = fcc->calling_scope;
3215                return 1;
3216            }
3217
3218            ret = zend_is_callable_check_func(check_flags, callable, fcc, 0, error TSRMLS_CC);
3219            if (fcc == &fcc_local &&
3220                fcc->function_handler &&
3221                ((fcc->function_handler->type == ZEND_INTERNAL_FUNCTION &&
3222                  (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) ||
3223                 fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
3224                 fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
3225                if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
3226                    zend_string_release(fcc->function_handler->common.function_name);
3227                }
3228                efree(fcc->function_handler);
3229            }
3230            return ret;
3231
3232        case IS_ARRAY:
3233            {
3234                zval *method = NULL;
3235                zval *obj = NULL;
3236                int strict_class = 0;
3237
3238                if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
3239                    obj = zend_hash_index_find(Z_ARRVAL_P(callable), 0);
3240                    method = zend_hash_index_find(Z_ARRVAL_P(callable), 1);
3241                }
3242
3243                do {
3244                    if (obj == NULL || method == NULL) {
3245                        break;
3246                    }
3247
3248                    ZVAL_DEREF(method);
3249                    if (Z_TYPE_P(method) != IS_STRING) {
3250                        break;
3251                    }
3252
3253                    ZVAL_DEREF(obj);
3254                    if (Z_TYPE_P(obj) == IS_STRING) {
3255                        if (callable_name) {
3256                            char *ptr;
3257
3258
3259                            *callable_name = zend_string_alloc(Z_STRLEN_P(obj) + Z_STRLEN_P(method) + sizeof("::") - 1, 0);
3260                            ptr = (*callable_name)->val;
3261                            memcpy(ptr, Z_STRVAL_P(obj), Z_STRLEN_P(obj));
3262                            ptr += Z_STRLEN_P(obj);
3263                            memcpy(ptr, "::", sizeof("::") - 1);
3264                            ptr += sizeof("::") - 1;
3265                            memcpy(ptr, Z_STRVAL_P(method), Z_STRLEN_P(method) + 1);
3266                        }
3267
3268                        if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3269                            return 1;
3270                        }
3271
3272                        if (!zend_is_callable_check_class(Z_STR_P(obj), fcc, &strict_class, error TSRMLS_CC)) {
3273                            return 0;
3274                        }
3275
3276                    } else if (Z_TYPE_P(obj) == IS_OBJECT) {
3277                        if (!EG(objects_store).object_buckets ||
3278                            !IS_OBJ_VALID(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(obj)])) {
3279                            return 0;
3280                        }
3281
3282                        fcc->calling_scope = Z_OBJCE_P(obj); /* TBFixed: what if it's overloaded? */
3283
3284                        fcc->object = Z_OBJ_P(obj);
3285
3286                        if (callable_name) {
3287                            char *ptr;
3288
3289                            *callable_name = zend_string_alloc(fcc->calling_scope->name->len + Z_STRLEN_P(method) + sizeof("::") - 1, 0);
3290                            ptr = (*callable_name)->val;
3291                            memcpy(ptr, fcc->calling_scope->name->val, fcc->calling_scope->name->len);
3292                            ptr += fcc->calling_scope->name->len;
3293                            memcpy(ptr, "::", sizeof("::") - 1);
3294                            ptr += sizeof("::") - 1;
3295                            memcpy(ptr, Z_STRVAL_P(method), Z_STRLEN_P(method) + 1);
3296                        }
3297
3298                        if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3299                            fcc->called_scope = fcc->calling_scope;
3300                            return 1;
3301                        }
3302                    } else {
3303                        break;
3304                    }
3305
3306                    ret = zend_is_callable_check_func(check_flags, method, fcc, strict_class, error TSRMLS_CC);
3307                    if (fcc == &fcc_local &&
3308                        fcc->function_handler &&
3309                        ((fcc->function_handler->type == ZEND_INTERNAL_FUNCTION &&
3310                          (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) ||
3311                         fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
3312                         fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
3313                        if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
3314                            zend_string_release(fcc->function_handler->common.function_name);
3315                        }
3316                        efree(fcc->function_handler);
3317                    }
3318                    return ret;
3319
3320                } while (0);
3321                if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
3322                    if (!obj || (!Z_ISREF_P(obj)?
3323                                (Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_OBJECT) :
3324                                (Z_TYPE_P(Z_REFVAL_P(obj)) != IS_STRING && Z_TYPE_P(Z_REFVAL_P(obj)) != IS_OBJECT))) {
3325                        if (error) zend_spprintf(error, 0, "first array member is not a valid class name or object");
3326                    } else {
3327                        if (error) zend_spprintf(error, 0, "second array member is not a valid method");
3328                    }
3329                } else {
3330                    if (error) zend_spprintf(error, 0, "array must have exactly two members");
3331                }
3332                if (callable_name) {
3333                    *callable_name = zend_string_init("Array", sizeof("Array")-1, 0);
3334                }
3335            }
3336            return 0;
3337
3338        case IS_OBJECT:
3339            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) {
3340                fcc->called_scope = fcc->calling_scope;
3341                if (callable_name) {
3342                    zend_class_entry *ce = Z_OBJCE_P(callable); /* TBFixed: what if it's overloaded? */
3343
3344                    *callable_name = zend_string_alloc(ce->name->len + sizeof("::__invoke") - 1, 0);
3345                    memcpy((*callable_name)->val, ce->name->val, ce->name->len);
3346                    memcpy((*callable_name)->val + ce->name->len, "::__invoke", sizeof("::__invoke"));
3347                }
3348                return 1;
3349            }
3350            /* break missing intentionally */
3351
3352        default:
3353            if (callable_name) {
3354                *callable_name = zval_get_string(callable);
3355            }
3356            if (error) zend_spprintf(error, 0, "no array or string given");
3357            return 0;
3358    }
3359}
3360/* }}} */
3361
3362ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, zend_string **callable_name TSRMLS_DC) /* {{{ */
3363{
3364    return zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, NULL TSRMLS_CC);
3365}
3366/* }}} */
3367
3368ZEND_API zend_bool zend_make_callable(zval *callable, zend_string **callable_name TSRMLS_DC) /* {{{ */
3369{
3370    zend_fcall_info_cache fcc;
3371
3372    if (zend_is_callable_ex(callable, NULL, IS_CALLABLE_STRICT, callable_name, &fcc, NULL TSRMLS_CC)) {
3373        if (Z_TYPE_P(callable) == IS_STRING && fcc.calling_scope) {
3374            zval_dtor(callable);
3375            array_init(callable);
3376            add_next_index_str(callable, zend_string_copy(fcc.calling_scope->name));
3377            add_next_index_str(callable, zend_string_copy(fcc.function_handler->common.function_name));
3378        }
3379        if (fcc.function_handler &&
3380            ((fcc.function_handler->type == ZEND_INTERNAL_FUNCTION &&
3381              (fcc.function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) ||
3382             fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
3383             fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
3384            if (fcc.function_handler->type != ZEND_OVERLOADED_FUNCTION) {
3385                zend_string_release(fcc.function_handler->common.function_name);
3386            }
3387            efree(fcc.function_handler);
3388        }
3389        return 1;
3390    }
3391    return 0;
3392}
3393/* }}} */
3394
3395ZEND_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) /* {{{ */
3396{
3397    if (!zend_is_callable_ex(callable, NULL, check_flags, callable_name, fcc, error TSRMLS_CC)) {
3398        return FAILURE;
3399    }
3400
3401    fci->size = sizeof(*fci);
3402    fci->function_table = fcc->calling_scope ? &fcc->calling_scope->function_table : EG(function_table);
3403    fci->object = fcc->object;
3404    ZVAL_COPY_VALUE(&fci->function_name, callable);
3405    fci->retval = NULL;
3406    fci->param_count = 0;
3407    fci->params = NULL;
3408    fci->no_separation = 1;
3409    fci->symbol_table = NULL;
3410
3411    return SUCCESS;
3412}
3413/* }}} */
3414
3415ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, int free_mem) /* {{{ */
3416{
3417    if (fci->params) {
3418        uint32_t i;
3419
3420        for (i = 0; i < fci->param_count; i++) {
3421            zval_ptr_dtor(&fci->params[i]);
3422        }
3423        if (free_mem) {
3424            efree(fci->params);
3425            fci->params = NULL;
3426        }
3427    }
3428    fci->param_count = 0;
3429}
3430/* }}} */
3431
3432ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, int *param_count, zval **params) /* {{{ */
3433{
3434    *param_count = fci->param_count;
3435    *params = fci->params;
3436    fci->param_count = 0;
3437    fci->params = NULL;
3438}
3439/* }}} */
3440
3441ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, int param_count, zval *params) /* {{{ */
3442{
3443    zend_fcall_info_args_clear(fci, 1);
3444    fci->param_count = param_count;
3445    fci->params = params;
3446}
3447/* }}} */
3448
3449ZEND_API int zend_fcall_info_args_ex(zend_fcall_info *fci, zend_function *func, zval *args TSRMLS_DC) /* {{{ */
3450{
3451    zval *arg, *params;
3452    uint32_t n = 1;
3453
3454    zend_fcall_info_args_clear(fci, !args);
3455
3456    if (!args) {
3457        return SUCCESS;
3458    }
3459
3460    if (Z_TYPE_P(args) != IS_ARRAY) {
3461        return FAILURE;
3462    }
3463
3464    fci->param_count = zend_hash_num_elements(Z_ARRVAL_P(args));
3465    fci->params = params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
3466
3467    ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(args), arg) {
3468        if (func && !Z_ISREF_P(arg) && ARG_SHOULD_BE_SENT_BY_REF(func, n)) {
3469            ZVAL_NEW_REF(params, arg);
3470            if (Z_REFCOUNTED_P(arg)) {
3471                Z_ADDREF_P(arg);
3472            }
3473        } else {
3474            ZVAL_COPY(params, arg);
3475        }
3476        params++;
3477        n++;
3478    } ZEND_HASH_FOREACH_END();
3479
3480    return SUCCESS;
3481}
3482/* }}} */
3483
3484ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC) /* {{{ */
3485{
3486    return zend_fcall_info_args_ex(fci, NULL, args TSRMLS_CC);
3487}
3488/* }}} */
3489
3490ZEND_API int zend_fcall_info_argp(zend_fcall_info *fci TSRMLS_DC, int argc, zval *argv) /* {{{ */
3491{
3492    int i;
3493
3494    if (argc < 0) {
3495        return FAILURE;
3496    }
3497
3498    zend_fcall_info_args_clear(fci, !argc);
3499
3500    if (argc) {
3501        fci->param_count = argc;
3502        fci->params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
3503
3504        for (i = 0; i < argc; ++i) {
3505            ZVAL_COPY_VALUE(&fci->params[i], &argv[i]);
3506        }
3507    }
3508
3509    return SUCCESS;
3510}
3511/* }}} */
3512
3513ZEND_API int zend_fcall_info_argv(zend_fcall_info *fci TSRMLS_DC, int argc, va_list *argv) /* {{{ */
3514{
3515    int i;
3516    zval *arg;
3517
3518    if (argc < 0) {
3519        return FAILURE;
3520    }
3521
3522    zend_fcall_info_args_clear(fci, !argc);
3523
3524    if (argc) {
3525        fci->param_count = argc;
3526        fci->params = (zval *) erealloc(fci->params, fci->param_count * sizeof(zval));
3527
3528        for (i = 0; i < argc; ++i) {
3529            arg = va_arg(*argv, zval *);
3530            ZVAL_COPY_VALUE(&fci->params[i], arg);
3531        }
3532    }
3533
3534    return SUCCESS;
3535}
3536/* }}} */
3537
3538ZEND_API int zend_fcall_info_argn(zend_fcall_info *fci TSRMLS_DC, int argc, ...) /* {{{ */
3539{
3540    int ret;
3541    va_list argv;
3542
3543    va_start(argv, argc);
3544    ret = zend_fcall_info_argv(fci TSRMLS_CC, argc, &argv);
3545    va_end(argv);
3546
3547    return ret;
3548}
3549/* }}} */
3550
3551ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval *retval_ptr, zval *args TSRMLS_DC) /* {{{ */
3552{
3553    zval retval, *org_params = NULL;
3554    int result, org_count = 0;
3555
3556    fci->retval = retval_ptr ? retval_ptr : &retval;
3557    if (args) {
3558        zend_fcall_info_args_save(fci, &org_count, &org_params);
3559        zend_fcall_info_args(fci, args TSRMLS_CC);
3560    }
3561    result = zend_call_function(fci, fcc TSRMLS_CC);
3562
3563    if (!retval_ptr && Z_TYPE(retval) != IS_UNDEF) {
3564        zval_ptr_dtor(&retval);
3565    }
3566    if (args) {
3567        zend_fcall_info_args_restore(fci, org_count, org_params);
3568    }
3569    return result;
3570}
3571/* }}} */
3572
3573ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */
3574{
3575    zend_string *lname;
3576    size_t name_len = strlen(module_name);
3577    zend_module_entry *module;
3578
3579    lname = zend_string_alloc(name_len, 0);
3580    zend_str_tolower_copy(lname->val, module_name, name_len);
3581    module = zend_hash_find_ptr(&module_registry, lname);
3582    zend_string_free(lname);
3583    return module ? module->version : NULL;
3584}
3585/* }}} */
3586
3587ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment TSRMLS_DC) /* {{{ */
3588{
3589    zend_property_info *property_info, *property_info_ptr;
3590
3591    if (ce->type == ZEND_INTERNAL_CLASS) {
3592        property_info = pemalloc(sizeof(zend_property_info), 1);
3593    } else {
3594        property_info = zend_arena_alloc(&CG(arena), sizeof(zend_property_info));
3595    }
3596
3597    if (Z_CONSTANT_P(property)) {
3598        ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
3599    }
3600    if (!(access_type & ZEND_ACC_PPP_MASK)) {
3601        access_type |= ZEND_ACC_PUBLIC;
3602    }
3603    if (access_type & ZEND_ACC_STATIC) {
3604        if ((property_info_ptr = zend_hash_find_ptr(&ce->properties_info, name)) != NULL &&
3605            (property_info_ptr->flags & ZEND_ACC_STATIC) != 0) {
3606            property_info->offset = property_info_ptr->offset;
3607            zval_ptr_dtor(&ce->default_static_members_table[property_info->offset]);
3608            zend_hash_del(&ce->properties_info, name);
3609        } else {
3610            property_info->offset = ce->default_static_members_count++;
3611            ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(zval) * ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
3612        }
3613        ZVAL_COPY_VALUE(&ce->default_static_members_table[property_info->offset], property);
3614        if (ce->type == ZEND_USER_CLASS) {
3615            ce->static_members_table = ce->default_static_members_table;
3616        }
3617    } else {
3618        if ((property_info_ptr = zend_hash_find_ptr(&ce->properties_info, name)) != NULL &&
3619            (property_info_ptr->flags & ZEND_ACC_STATIC) == 0) {
3620            property_info->offset = property_info_ptr->offset;
3621            zval_ptr_dtor(&ce->default_properties_table[property_info->offset]);
3622            zend_hash_del(&ce->properties_info, name);
3623        } else {
3624            property_info->offset = ce->default_properties_count++;
3625            ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
3626        }
3627        ZVAL_COPY_VALUE(&ce->default_properties_table[property_info->offset], property);
3628    }
3629    if (ce->type & ZEND_INTERNAL_CLASS) {
3630        switch(Z_TYPE_P(property)) {
3631            case IS_ARRAY:
3632            case IS_OBJECT:
3633            case IS_RESOURCE:
3634                zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
3635                break;
3636            default:
3637                break;
3638        }
3639    }
3640    switch (access_type & ZEND_ACC_PPP_MASK) {
3641        case ZEND_ACC_PRIVATE: {
3642                property_info->name = zend_mangle_property_name(ce->name->val, ce->name->len, name->val, name->len, ce->type & ZEND_INTERNAL_CLASS);
3643            }
3644            break;
3645        case ZEND_ACC_PROTECTED: {
3646                property_info->name = zend_mangle_property_name("*", 1, name->val, name->len, ce->type & ZEND_INTERNAL_CLASS);
3647            }
3648            break;
3649        case ZEND_ACC_PUBLIC:
3650            property_info->name = zend_string_copy(name);
3651            break;
3652    }
3653
3654    property_info->name = zend_new_interned_string(property_info->name TSRMLS_CC);
3655    property_info->flags = access_type;
3656    property_info->doc_comment = doc_comment;
3657    property_info->ce = ce;
3658    zend_hash_update_ptr(&ce->properties_info, name, property_info);
3659
3660    return SUCCESS;
3661}
3662/* }}} */
3663
3664ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, size_t name_length, zval *property, int access_type TSRMLS_DC) /* {{{ */
3665{
3666    zend_string *key = zend_string_init(name, name_length, ce->type & ZEND_INTERNAL_CLASS);
3667    int ret = zend_declare_property_ex(ce, key, property, access_type, NULL TSRMLS_CC);
3668    zend_string_release(key);
3669    return ret;
3670}
3671/* }}} */
3672
3673ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, size_t name_length, int access_type TSRMLS_DC) /* {{{ */
3674{
3675    zval property;
3676
3677    ZVAL_NULL(&property);
3678    return zend_declare_property(ce, name, name_length, &property, access_type TSRMLS_CC);
3679}
3680/* }}} */
3681
3682ZEND_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) /* {{{ */
3683{
3684    zval property;
3685
3686    ZVAL_BOOL(&property, value);
3687    return zend_declare_property(ce, name, name_length, &property, access_type TSRMLS_CC);
3688}
3689/* }}} */
3690
3691ZEND_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) /* {{{ */
3692{
3693    zval property;
3694
3695    ZVAL_LONG(&property, value);
3696    return zend_declare_property(ce, name, name_length, &property, access_type TSRMLS_CC);
3697}
3698/* }}} */
3699
3700ZEND_API int zend_declare_property_double(zend_class_entry *ce, const char *name, size_t name_length, double value, int access_type TSRMLS_DC) /* {{{ */
3701{
3702    zval property;
3703
3704    ZVAL_DOUBLE(&property, value);
3705    return zend_declare_property(ce, name, name_length, &property, access_type TSRMLS_CC);
3706}
3707/* }}} */
3708
3709ZEND_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) /* {{{ */
3710{
3711    zval property;
3712
3713    ZVAL_NEW_STR(&property, zend_string_init(value, strlen(value), ce->type & ZEND_INTERNAL_CLASS));
3714    return zend_declare_property(ce, name, name_length, &property, access_type TSRMLS_CC);
3715}
3716/* }}} */
3717
3718ZEND_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) /* {{{ */
3719{
3720    zval property;
3721
3722    ZVAL_NEW_STR(&property, zend_string_init(value, value_len, ce->type & ZEND_INTERNAL_CLASS));
3723    return zend_declare_property(ce, name, name_length, &property, access_type TSRMLS_CC);
3724}
3725/* }}} */
3726
3727ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value TSRMLS_DC) /* {{{ */
3728{
3729    if (Z_CONSTANT_P(value)) {
3730        ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
3731    }
3732    return zend_hash_str_update(&ce->constants_table, name, name_length, value) ?
3733        SUCCESS : FAILURE;
3734}
3735/* }}} */
3736
3737ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length TSRMLS_DC) /* {{{ */
3738{
3739    zval constant;
3740
3741    ZVAL_NULL(&constant);
3742    return zend_declare_class_constant(ce, name, name_length, &constant TSRMLS_CC);
3743}
3744/* }}} */
3745
3746ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value TSRMLS_DC) /* {{{ */
3747{
3748    zval constant;
3749
3750    ZVAL_LONG(&constant, value);
3751    return zend_declare_class_constant(ce, name, name_length, &constant TSRMLS_CC);
3752}
3753/* }}} */
3754
3755ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_bool value TSRMLS_DC) /* {{{ */
3756{
3757    zval constant;
3758
3759    ZVAL_BOOL(&constant, value);
3760    return zend_declare_class_constant(ce, name, name_length, &constant TSRMLS_CC);
3761}
3762/* }}} */
3763
3764ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value TSRMLS_DC) /* {{{ */
3765{
3766    zval constant;
3767
3768    ZVAL_DOUBLE(&constant, value);
3769    return zend_declare_class_constant(ce, name, name_length, &constant TSRMLS_CC);
3770}
3771/* }}} */
3772
3773ZEND_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) /* {{{ */
3774{
3775    zval constant;
3776
3777    ZVAL_NEW_STR(&constant, zend_string_init(value, value_length, ce->type & ZEND_INTERNAL_CLASS));
3778    return zend_declare_class_constant(ce, name, name_length, &constant TSRMLS_CC);
3779}
3780/* }}} */
3781
3782ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value TSRMLS_DC) /* {{{ */
3783{
3784    return zend_declare_class_constant_stringl(ce, name, name_length, value, strlen(value) TSRMLS_CC);
3785}
3786/* }}} */
3787
3788ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zval *value TSRMLS_DC) /* {{{ */
3789{
3790    zval property;
3791    zend_class_entry *old_scope = EG(scope);
3792
3793    EG(scope) = scope;
3794
3795    if (!Z_OBJ_HT_P(object)->write_property) {
3796        zend_error(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, Z_OBJCE_P(object)->name->val);
3797    }
3798    ZVAL_STRINGL(&property, name, name_length);
3799    Z_OBJ_HT_P(object)->write_property(object, &property, value, NULL TSRMLS_CC);
3800    zval_ptr_dtor(&property);
3801
3802    EG(scope) = old_scope;
3803}
3804/* }}} */
3805
3806ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, size_t name_length TSRMLS_DC) /* {{{ */
3807{
3808    zval tmp;
3809
3810    ZVAL_NULL(&tmp);
3811    zend_update_property(scope, object, name, name_length, &tmp TSRMLS_CC);
3812}
3813/* }}} */
3814
3815ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_long value TSRMLS_DC) /* {{{ */
3816{
3817    zval tmp;
3818
3819    ZVAL_BOOL(&tmp, value);
3820    zend_update_property(scope, object, name, name_length, &tmp TSRMLS_CC);
3821}
3822/* }}} */
3823
3824ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_long value TSRMLS_DC) /* {{{ */
3825{
3826    zval tmp;
3827
3828    ZVAL_LONG(&tmp, value);
3829    zend_update_property(scope, object, name, name_length, &tmp TSRMLS_CC);
3830}
3831/* }}} */
3832
3833ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, const char *name, size_t name_length, double value TSRMLS_DC) /* {{{ */
3834{
3835    zval tmp;
3836
3837    ZVAL_DOUBLE(&tmp, value);
3838    zend_update_property(scope, object, name, name_length, &tmp TSRMLS_CC);
3839}
3840/* }}} */
3841
3842ZEND_API void zend_update_property_str(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_string *value TSRMLS_DC) /* {{{ */
3843{
3844    zval tmp;
3845
3846    ZVAL_STR(&tmp, value);
3847    zend_update_property(scope, object, name, name_length, &tmp TSRMLS_CC);
3848}
3849/* }}} */
3850
3851ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, const char *name, size_t name_length, const char *value TSRMLS_DC) /* {{{ */
3852{
3853    zval tmp;
3854
3855    ZVAL_STRING(&tmp, value);
3856    Z_SET_REFCOUNT(tmp, 0);
3857    zend_update_property(scope, object, name, name_length, &tmp TSRMLS_CC);
3858}
3859/* }}} */
3860
3861ZEND_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) /* {{{ */
3862{
3863    zval tmp;
3864
3865    ZVAL_STRINGL(&tmp, value, value_len);
3866    Z_SET_REFCOUNT(tmp, 0);
3867    zend_update_property(scope, object, name, name_length, &tmp TSRMLS_CC);
3868}
3869/* }}} */
3870
3871ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, size_t name_length, zval *value TSRMLS_DC) /* {{{ */
3872{
3873    zval *property;
3874    zend_class_entry *old_scope = EG(scope);
3875    zend_string *key = zend_string_init(name, name_length, 0);
3876
3877    EG(scope) = scope;
3878    property = zend_std_get_static_property(scope, key, 0, NULL TSRMLS_CC);
3879    EG(scope) = old_scope;
3880    zend_string_free(key);
3881    if (!property) {
3882        return FAILURE;
3883    } else {
3884        if (property != value) {
3885            if (Z_ISREF_P(property)) {
3886                zval_dtor(property);
3887                ZVAL_COPY_VALUE(property, value);
3888                if (Z_REFCOUNT_P(value) > 0) {
3889                    zval_opt_copy_ctor(property);
3890                }
3891            } else {
3892                zval garbage;
3893
3894                ZVAL_COPY_VALUE(&garbage, property);
3895                if (Z_REFCOUNTED_P(value)) {
3896                    Z_ADDREF_P(value);
3897                    if (Z_ISREF_P(value)) {
3898                        SEPARATE_ZVAL(value);
3899                    }
3900                }
3901                ZVAL_COPY_VALUE(property, value);
3902                zval_ptr_dtor(&garbage);
3903            }
3904        }
3905        return SUCCESS;
3906    }
3907}
3908/* }}} */
3909
3910ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const char *name, size_t name_length TSRMLS_DC) /* {{{ */
3911{
3912    zval tmp;
3913
3914    ZVAL_NULL(&tmp);
3915    return zend_update_static_property(scope, name, name_length, &tmp TSRMLS_CC);
3916}
3917/* }}} */
3918
3919ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const char *name, size_t name_length, zend_long value TSRMLS_DC) /* {{{ */
3920{
3921    zval tmp;
3922
3923    ZVAL_BOOL(&tmp, value);
3924    return zend_update_static_property(scope, name, name_length, &tmp TSRMLS_CC);
3925}
3926/* }}} */
3927
3928ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const char *name, size_t name_length, zend_long value TSRMLS_DC) /* {{{ */
3929{
3930    zval tmp;
3931
3932    ZVAL_LONG(&tmp, value);
3933    return zend_update_static_property(scope, name, name_length, &tmp TSRMLS_CC);
3934}
3935/* }}} */
3936
3937ZEND_API int zend_update_static_property_double(zend_class_entry *scope, const char *name, size_t name_length, double value TSRMLS_DC) /* {{{ */
3938{
3939    zval tmp;
3940
3941    ZVAL_DOUBLE(&tmp, value);
3942    return zend_update_static_property(scope, name, name_length, &tmp TSRMLS_CC);
3943}
3944/* }}} */
3945
3946ZEND_API int zend_update_static_property_string(zend_class_entry *scope, const char *name, size_t name_length, const char *value TSRMLS_DC) /* {{{ */
3947{
3948    zval tmp;
3949
3950    ZVAL_STRING(&tmp, value);
3951    Z_SET_REFCOUNT(tmp, 0);
3952    return zend_update_static_property(scope, name, name_length, &tmp TSRMLS_CC);
3953}
3954/* }}} */
3955
3956ZEND_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) /* {{{ */
3957{
3958    zval tmp;
3959
3960    ZVAL_STRINGL(&tmp, value, value_len);
3961    Z_SET_REFCOUNT(tmp, 0);
3962    return zend_update_static_property(scope, name, name_length, &tmp TSRMLS_CC);
3963}
3964/* }}} */
3965
3966ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const char *name, size_t name_length, zend_bool silent TSRMLS_DC) /* {{{ */
3967{
3968    zval property, *value;
3969    zend_class_entry *old_scope = EG(scope);
3970    zval rv;
3971
3972    EG(scope) = scope;
3973
3974    if (!Z_OBJ_HT_P(object)->read_property) {
3975        zend_error(E_CORE_ERROR, "Property %s of class %s cannot be read", name, Z_OBJCE_P(object)->name->val);
3976    }
3977
3978    ZVAL_STRINGL(&property, name, name_length);
3979    value = Z_OBJ_HT_P(object)->read_property(object, &property, silent?BP_VAR_IS:BP_VAR_R, NULL, &rv TSRMLS_CC);
3980    zval_ptr_dtor(&property);
3981
3982    EG(scope) = old_scope;
3983    return value;
3984}
3985/* }}} */
3986
3987ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, size_t name_length, zend_bool silent TSRMLS_DC) /* {{{ */
3988{
3989    zval *property;
3990    zend_class_entry *old_scope = EG(scope);
3991    zend_string *key = zend_string_init(name, name_length, 0);
3992
3993    EG(scope) = scope;
3994    property = zend_std_get_static_property(scope, key, silent, NULL TSRMLS_CC);
3995    EG(scope) = old_scope;
3996    zend_string_free(key);
3997
3998    return property;
3999}
4000/* }}} */
4001
4002ZEND_API void zend_save_error_handling(zend_error_handling *current TSRMLS_DC) /* {{{ */
4003{
4004    current->handling = EG(error_handling);
4005    current->exception = EG(exception_class);
4006    ZVAL_COPY(&current->user_handler, &EG(user_error_handler));
4007}
4008/* }}} */
4009
4010ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current TSRMLS_DC) /* {{{ */
4011{
4012    if (current) {
4013        zend_save_error_handling(current TSRMLS_CC);
4014        if (error_handling != EH_NORMAL && Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
4015            zval_ptr_dtor(&EG(user_error_handler));
4016            ZVAL_UNDEF(&EG(user_error_handler));
4017        }
4018    }
4019    EG(error_handling) = error_handling;
4020    EG(exception_class) = error_handling == EH_THROW ? exception_class : NULL;
4021}
4022/* }}} */
4023
4024static int same_zval(zval *zv1, zval *zv2)  /* {{{ */
4025{
4026    if (Z_TYPE_P(zv1) != Z_TYPE_P(zv2)) {
4027        return 0;
4028    }
4029    switch (Z_TYPE_P(zv1)) {
4030        case IS_UNDEF:
4031        case IS_NULL:
4032        case IS_FALSE:
4033        case IS_TRUE:
4034            return 1;
4035        case IS_LONG:
4036            return Z_LVAL_P(zv1) == Z_LVAL_P(zv2);
4037        case IS_DOUBLE:
4038            return Z_LVAL_P(zv1) == Z_LVAL_P(zv2);
4039        case IS_STRING:
4040        case IS_ARRAY:
4041        case IS_OBJECT:
4042        case IS_RESOURCE:
4043            return Z_COUNTED_P(zv1) == Z_COUNTED_P(zv2);
4044        default:
4045            return 0;
4046    }
4047}
4048/* }}} */
4049
4050ZEND_API void zend_restore_error_handling(zend_error_handling *saved TSRMLS_DC) /* {{{ */
4051{
4052    EG(error_handling) = saved->handling;
4053    EG(exception_class) = saved->handling == EH_THROW ? saved->exception : NULL;
4054    if (Z_TYPE(saved->user_handler) != IS_UNDEF
4055        && !same_zval(&saved->user_handler, &EG(user_error_handler))) {
4056        zval_ptr_dtor(&EG(user_error_handler));
4057        ZVAL_COPY_VALUE(&EG(user_error_handler), &saved->user_handler);
4058    } else if (Z_TYPE(saved->user_handler)) {
4059        zval_ptr_dtor(&saved->user_handler);
4060    }
4061    ZVAL_UNDEF(&saved->user_handler);
4062}
4063/* }}} */
4064
4065ZEND_API zend_string* zend_find_alias_name(zend_class_entry *ce, zend_string *name) /* {{{ */
4066{
4067    zend_trait_alias *alias, **alias_ptr;
4068
4069    if ((alias_ptr = ce->trait_aliases)) {
4070        alias = *alias_ptr;
4071        while (alias) {
4072            if (alias->alias->len == name->len &&
4073                !strncasecmp(name->val, alias->alias->val, alias->alias->len)) {
4074                return alias->alias;
4075            }
4076            alias_ptr++;
4077            alias = *alias_ptr;
4078        }
4079    }
4080
4081    return name;
4082}
4083/* }}} */
4084
4085ZEND_API zend_string *zend_resolve_method_name(zend_class_entry *ce, zend_function *f) /* {{{ */
4086{
4087    zend_function *func;
4088    HashTable *function_table;
4089    zend_string *name;
4090
4091    if (f->common.type != ZEND_USER_FUNCTION ||
4092        *(f->op_array.refcount) < 2 ||
4093        !f->common.scope ||
4094        !f->common.scope->trait_aliases) {
4095        return f->common.function_name;
4096    }
4097
4098    function_table = &ce->function_table;
4099    ZEND_HASH_FOREACH_STR_KEY_PTR(function_table, name, func) {
4100        if (func == f) {
4101            if (!name) {
4102                return f->common.function_name;
4103            }
4104            if (name->len == f->common.function_name->len &&
4105                !strncasecmp(name->val, f->common.function_name->val, f->common.function_name->len)) {
4106                return f->common.function_name;
4107            }
4108            return zend_find_alias_name(f->common.scope, name);
4109        }
4110    } ZEND_HASH_FOREACH_END();
4111    return f->common.function_name;
4112}
4113/* }}} */
4114
4115ZEND_API void zend_ctor_make_null(zend_execute_data *execute_data) /* {{{ */
4116{
4117    if (EX(return_value)) {
4118/*
4119        if (Z_TYPE_P(EX(return_value)) == IS_OBJECT) {
4120            zend_object *object = Z_OBJ_P(EX(return_value));
4121            zend_execute_data *ex = EX(prev_execute_data);
4122
4123            while (ex && Z_OBJ(ex->This) == object) {
4124                if (ex->func) {
4125                    if (ZEND_USER_CODE(ex->func->type)) {
4126                        if (ex->func->op_array.this_var != -1) {
4127                            zval *this_var = EX_VAR_2(ex, ex->func->op_array.this_var);
4128                            if (this_var != EX(return_value)) {
4129                                zval_ptr_dtor(this_var);
4130                                ZVAL_NULL(this_var);
4131                            }
4132                        }
4133                    }
4134                }
4135                Z_OBJ(ex->This) = NULL;
4136                ZVAL_NULL(&ex->This);
4137                ex = ex->prev_execute_data;
4138            }
4139        }
4140*/
4141        zval_ptr_dtor(EX(return_value));
4142        Z_OBJ_P(EX(return_value)) = NULL;
4143        ZVAL_NULL(EX(return_value));
4144    }
4145}
4146/* }}} */
4147
4148/*
4149 * Local variables:
4150 * tab-width: 4
4151 * c-basic-offset: 4
4152 * indent-tabs-mode: t
4153 * End:
4154 */
4155