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