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