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