]> granicus.if.org Git - php/commitdiff
Use zend_string* for op_array->arg_info[]->name and op_array->arg_info[]->class_name...
authorDmitry Stogov <dmitry@zend.com>
Wed, 3 Dec 2014 13:56:09 +0000 (16:56 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 3 Dec 2014 13:56:09 +0000 (16:56 +0300)
15 files changed:
Zend/zend_API.c
Zend/zend_API.h
Zend/zend_closures.c
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_execute.h
Zend/zend_inheritance.c
Zend/zend_opcode.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
ext/opcache/zend_persist.c
ext/opcache/zend_persist_calc.c
ext/pdo/pdo_dbh.c
ext/reflection/php_reflection.c

index e95276d4c80a265778b08328b196c2c9f82fad86..10efd7ab5bb841b965486f8ffb4129e1d33084a4 100644 (file)
@@ -2192,7 +2192,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
                if (ptr->arg_info) {
                        zend_internal_function_info *info = (zend_internal_function_info*)ptr->arg_info;
                        
-                       internal_function->arg_info = (zend_arg_info*)ptr->arg_info+1;
+                       internal_function->arg_info = (zend_internal_arg_info*)ptr->arg_info+1;
                        internal_function->num_args = ptr->num_args;
                        /* Currently you cannot denote that the function can accept less arguments than num_args */
                        if (info->required_num_args == -1) {
index 6817e85f9b57d72a82228320728730448193d3f4..bee797b7da6be3b1fb74363898b13e4a9348c439 100644 (file)
@@ -35,7 +35,7 @@ BEGIN_EXTERN_C()
 typedef struct _zend_function_entry {
        const char *fname;
        void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
-       const struct _zend_arg_info *arg_info;
+       const struct _zend_internal_arg_info *arg_info;
        uint32_t num_args;
        uint32_t flags;
 } zend_function_entry;
@@ -98,16 +98,16 @@ typedef struct _zend_fcall_info_cache {
 
 #define ZEND_FE_END            { NULL, NULL, NULL, 0, 0 }
 
-#define ZEND_ARG_INFO(pass_by_ref, name)                                                       { #name, sizeof(#name)-1, NULL, 0, 0, pass_by_ref, 0, 0 },
-#define ZEND_ARG_PASS_INFO(pass_by_ref)                                                                { NULL, 0, NULL, 0, 0, pass_by_ref, 0, 0 },
-#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, sizeof(#name)-1, #classname, sizeof(#classname)-1, IS_OBJECT, pass_by_ref, allow_null, 0 },
-#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, sizeof(#name)-1, NULL, 0, IS_ARRAY, pass_by_ref, allow_null, 0 },
-#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, sizeof(#name)-1, NULL, 0, type_hint, pass_by_ref, allow_null, 0 },
-#define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name)                                      { #name, sizeof(#name)-1, NULL, 0, 0, pass_by_ref, 0, 1 },
+#define ZEND_ARG_INFO(pass_by_ref, name)                                                        { #name, NULL, 0, pass_by_ref, 0, 0 },
+#define ZEND_ARG_PASS_INFO(pass_by_ref)                                                                 { NULL,  NULL, 0, pass_by_ref, 0, 0 },
+#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null)  { #name, #classname, IS_OBJECT, pass_by_ref, allow_null, 0 },
+#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null)           { #name, NULL, IS_ARRAY, pass_by_ref, allow_null, 0 },
+#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, NULL, type_hint, pass_by_ref, allow_null, 0 },
+#define ZEND_ARG_VARIADIC_INFO(pass_by_ref, name)                                       { #name, NULL, 0, pass_by_ref, 0, 1 },
 
 #define ZEND_BEGIN_ARG_INFO_EX(name, _unused, return_reference, required_num_args)     \
-       static const zend_arg_info name[] = {                                                                                                                                           \
-               { NULL, 0, NULL, required_num_args, 0, return_reference, 0, 0 },
+       static const zend_internal_arg_info name[] = {                                                                                                                                          \
+               { (const char*)(zend_uintptr_t)(required_num_args), NULL, 0, return_reference, 0, 0 },
 #define ZEND_BEGIN_ARG_INFO(name, _unused)     \
        ZEND_BEGIN_ARG_INFO_EX(name, 0, ZEND_RETURN_VALUE, -1)
 #define ZEND_END_ARG_INFO()            };
index e4827f83b772c7a462522c8093676b83fccf968a..bf0ba0ace405018b5e720d4859726013f4ee25ef 100644 (file)
@@ -182,6 +182,7 @@ ZEND_API zend_function *zend_get_closure_invoke_method(zend_object *object TSRML
        zend_function *invoke = (zend_function*)emalloc(sizeof(zend_function));
 
        invoke->common = closure->func.common;
+       /* TODO: return ZEND_INTERNAL_FUNCTION, but arg_info representation is suitable for ZEND_USER_FUNCTION ??? */
        invoke->type = ZEND_INTERNAL_FUNCTION;
        invoke->internal_function.fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER | (closure->func.common.fn_flags & ZEND_ACC_RETURN_REFERENCE);
        invoke->internal_function.handler = ZEND_MN(Closure___invoke);
@@ -370,7 +371,7 @@ static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp TSRMLS_
                                if (arg_info->name) {
                                        name = zend_strpprintf(0, "%s$%s",
                                                        arg_info->pass_by_reference ? "&" : "",
-                                                       arg_info->name);
+                                                       arg_info->name->val);
                                } else {
                                        name = zend_strpprintf(0, "%s$param%d",
                                                        arg_info->pass_by_reference ? "&" : "",
index cfc70af59023253edef545e9636c5031734fee33..086c7d0db165e99be08b87c51d10be9d422ffe3e 100644 (file)
@@ -3833,14 +3833,12 @@ void zend_compile_params(zend_ast *ast TSRMLS_DC) /* {{{ */
                opline->op1.num = i + 1;
 
                arg_info = &arg_infos[i];
-               arg_info->name = estrndup(name->val, name->len);
-               arg_info->name_len = (uint32_t)name->len;
+               arg_info->name = zend_string_copy(name);
                arg_info->pass_by_reference = is_ref;
                arg_info->is_variadic = is_variadic;
                arg_info->type_hint = 0;
                arg_info->allow_null = 1;
                arg_info->class_name = NULL;
-               arg_info->class_name_len = 0;
 
                if (type_ast) {
                        zend_bool has_null_default = default_ast
@@ -3877,10 +3875,7 @@ void zend_compile_params(zend_ast *ast TSRMLS_DC) /* {{{ */
                                }
 
                                arg_info->type_hint = IS_OBJECT;
-                               arg_info->class_name = estrndup(class_name->val, class_name->len);
-                               arg_info->class_name_len = (uint32_t)class_name->len;
-
-                               zend_string_release(class_name);
+                               arg_info->class_name = class_name;
 
                                if (default_ast && !has_null_default && !Z_CONSTANT(default_node.u.constant)) {
                                                zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
index a885518caf78be12fdd0262739307f8530109b9b..63d67660c68e1043ffd975a256f987de3c313700 100644 (file)
@@ -245,26 +245,33 @@ typedef struct _zend_property_info {
 #define OBJ_PROP_TO_NUM(offset) \
        ((offset - OBJ_PROP_TO_OFFSET(0)) / sizeof(zval))
 
+/* arg_info for internal functions */
+typedef struct _zend_internal_arg_info { 
+       const char *name;
+       const char *class_name;
+       zend_uchar type_hint;
+       zend_uchar pass_by_reference;
+       zend_bool allow_null;
+       zend_bool is_variadic;
+} zend_internal_arg_info;
+
+/* arg_info for user functions */
 typedef struct _zend_arg_info {
-       const char *name;                       // TODO: convert into zend_string ???
-       uint32_t name_len;
-       const char *class_name;         // TODO: convert into zend_string ???
-       uint32_t class_name_len;
+       zend_string *name;
+       zend_string *class_name;
        zend_uchar type_hint;
        zend_uchar pass_by_reference;
        zend_bool allow_null;
        zend_bool is_variadic;
 } zend_arg_info;
 
-/* the following structure repeats the layout of zend_arg_info,
+/* the following structure repeats the layout of zend_internal_arg_info,
  * but its fields have different meaning. It's used as the first element of
  * arg_info array to define properties of internal functions.
  */
 typedef struct _zend_internal_function_info {
-       const char *_name;
-       uint32_t _name_len;
+       zend_uintptr_t required_num_args;
        const char *_class_name;
-       uint32_t required_num_args;
        zend_uchar _type_hint;
        zend_bool return_reference;
        zend_bool _allow_null;
@@ -330,7 +337,7 @@ typedef struct _zend_internal_function {
        zend_function *prototype;
        uint32_t num_args;
        uint32_t required_num_args;
-       zend_arg_info *arg_info;
+       zend_internal_arg_info *arg_info;
        /* END of common elements */
 
        void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
index e848e59decd646f5ebe5fcb774ea8bd1ae316552..a9fadd10da0c644db5ba8b95fb48292b191f19ad 100644 (file)
@@ -525,12 +525,12 @@ static inline zval* make_real_object(zval *object_ptr TSRMLS_DC)
        return object;
 }
 
-ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce TSRMLS_DC)
+ZEND_API char * zend_verify_internal_arg_class_kind(const zend_internal_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce TSRMLS_DC)
 {
        zend_string *key;
        ALLOCA_FLAG(use_heap);
 
-       STR_ALLOCA_INIT(key, cur_arg_info->class_name, cur_arg_info->class_name_len, use_heap);
+       STR_ALLOCA_INIT(key, cur_arg_info->class_name, strlen(cur_arg_info->class_name), use_heap);
        *pce = zend_fetch_class(key, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD) TSRMLS_CC);
        STR_ALLOCA_FREE(key, use_heap);
 
@@ -542,6 +542,18 @@ ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ch
        }
 }
 
+ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce TSRMLS_DC)
+{
+       *pce = zend_fetch_class(cur_arg_info->class_name, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD) TSRMLS_CC);
+
+       *class_name = (*pce) ? (*pce)->name->val : cur_arg_info->class_name->val;
+       if (*pce && (*pce)->ce_flags & ZEND_ACC_INTERFACE) {
+               return "implement interface ";
+       } else {
+               return "be an instance of ";
+       }
+}
+
 ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, uint32_t arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC)
 {
        zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
@@ -593,6 +605,55 @@ static int is_null_constant(zval *default_value TSRMLS_DC)
        return 0;
 }
 
+static void zend_verify_internal_arg_type(zend_function *zf, uint32_t arg_num, zval *arg TSRMLS_DC)
+{
+       zend_internal_arg_info *cur_arg_info;
+       char *need_msg;
+       zend_class_entry *ce;
+
+       if (UNEXPECTED(!zf->internal_function.arg_info)) {
+               return;
+       }
+
+       if (EXPECTED(arg_num <= zf->internal_function.num_args)) {
+               cur_arg_info = &zf->internal_function.arg_info[arg_num-1];
+       } else if (zf->internal_function.fn_flags & ZEND_ACC_VARIADIC) {
+               cur_arg_info = &zf->internal_function.arg_info[zf->internal_function.num_args-1];
+       } else {
+               return;
+       }
+
+       if (cur_arg_info->class_name) {
+               char *class_name;
+
+               ZVAL_DEREF(arg);
+               if (Z_TYPE_P(arg) == IS_OBJECT) {
+                       need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce TSRMLS_CC);
+                       if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) {
+                               zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg TSRMLS_CC);
+                       }
+               } else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) {
+                       need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce TSRMLS_CC);
+                       zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg TSRMLS_CC);
+               }
+       } else if (cur_arg_info->type_hint) {
+               if (cur_arg_info->type_hint == IS_ARRAY) {
+                       ZVAL_DEREF(arg);
+                       if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
+                               zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg TSRMLS_CC);
+                       }
+               } else if (cur_arg_info->type_hint == IS_CALLABLE) {
+                       if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL TSRMLS_CC) && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
+                               zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg TSRMLS_CC);
+                       }
+#if ZEND_DEBUG
+               } else {
+                       zend_error(E_ERROR, "Unknown typehint");
+#endif
+               }
+       }
+}
+
 static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value TSRMLS_DC)
 {
        zend_arg_info *cur_arg_info;
index ddd736c07e476943a516b66d2705e8f2fe876810..d4a46db0438787979b2b6ab194ac2d0ef7535f50 100644 (file)
@@ -48,6 +48,7 @@ ZEND_API int zend_eval_stringl(char *str, size_t str_len, zval *retval_ptr, char
 ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
 ZEND_API int zend_eval_stringl_ex(char *str, size_t str_len, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
 
+ZEND_API char * zend_verify_internal_arg_class_kind(const zend_internal_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce TSRMLS_DC);
 ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce TSRMLS_DC);
 ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, uint32_t arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg TSRMLS_DC);
 
index 43ef22074faf7adf963e86d5f79adb3a11763548..407acade0ef688805d642e442f11ecf147199acb 100644 (file)
@@ -283,25 +283,40 @@ static zend_bool zend_do_perform_implementation_check(const zend_function *fe, c
 
                if (fe_arg_info->class_name) {
                        zend_string *fe_class_name, *proto_class_name;
+                       const char *class_name;
 
-                       if (!strcasecmp(fe_arg_info->class_name, "parent") && proto->common.scope) {
+                       if (fe->type == ZEND_INTERNAL_FUNCTION) {                               
+                               fe_class_name = NULL;
+                               class_name = ((zend_internal_arg_info*)fe_arg_info)->class_name;
+                       } else {
+                               fe_class_name = fe_arg_info->class_name;
+                               class_name = fe_arg_info->class_name->val;
+                       }
+                       if (!strcasecmp(class_name, "parent") && proto->common.scope) {
                                fe_class_name = zend_string_copy(proto->common.scope->name);
-                       } else if (!strcasecmp(fe_arg_info->class_name, "self") && fe->common.scope) {
+                       } else if (!strcasecmp(class_name, "self") && fe->common.scope) {
                                fe_class_name = zend_string_copy(fe->common.scope->name);
+                       } else if (fe_class_name) {
+                               zend_string_addref(fe_class_name);
                        } else {
-                               fe_class_name = zend_string_init(
-                                       fe_arg_info->class_name,
-                                       fe_arg_info->class_name_len, 0);
+                               fe_class_name = zend_string_init(class_name, strlen(class_name), 0);
                        }
 
-                       if (!strcasecmp(proto_arg_info->class_name, "parent") && proto->common.scope && proto->common.scope->parent) {
+                       if (proto->type == ZEND_INTERNAL_FUNCTION) {                            
+                               proto_class_name = NULL;
+                               class_name = ((zend_internal_arg_info*)proto_arg_info)->class_name;
+                       } else {
+                               proto_class_name = proto_arg_info->class_name;
+                               class_name = proto_arg_info->class_name->val;
+                       }
+                       if (!strcasecmp(class_name, "parent") && proto->common.scope && proto->common.scope->parent) {
                                proto_class_name = zend_string_copy(proto->common.scope->parent->name);
-                       } else if (!strcasecmp(proto_arg_info->class_name, "self") && proto->common.scope) {
+                       } else if (!strcasecmp(class_name, "self") && proto->common.scope) {
                                proto_class_name = zend_string_copy(proto->common.scope->name);
+                       } else if (proto_class_name) {
+                               zend_string_addref(proto_class_name);
                        } else {
-                               proto_class_name = zend_string_init(
-                                       proto_arg_info->class_name,
-                                       proto_arg_info->class_name_len, 0);
+                               proto_class_name = zend_string_init(class_name, strlen(class_name), 0);
                        }
 
                        if (strcasecmp(fe_class_name->val, proto_class_name->val)!=0) {
@@ -373,15 +388,21 @@ static zend_string *zend_get_function_declaration(zend_function *fptr TSRMLS_DC)
                        if (arg_info->class_name) {
                                const char *class_name;
                                size_t class_name_len;
-                               if (!strcasecmp(arg_info->class_name, "self") && fptr->common.scope) {
+
+                               if (fptr->type == ZEND_INTERNAL_FUNCTION) {
+                                       class_name = ((zend_internal_arg_info*)arg_info)->class_name;
+                                       class_name_len = strlen(class_name);
+                               } else {
+                                       class_name = arg_info->class_name->val;
+                                       class_name_len = arg_info->class_name->len;
+                               }
+
+                               if (!strcasecmp(class_name, "self") && fptr->common.scope) {
                                        class_name = fptr->common.scope->name->val;
                                        class_name_len = fptr->common.scope->name->len;
-                               } else if (!strcasecmp(arg_info->class_name, "parent") && fptr->common.scope->parent) {
+                               } else if (!strcasecmp(class_name, "parent") && fptr->common.scope->parent) {
                                        class_name = fptr->common.scope->parent->name->val;
                                        class_name_len = fptr->common.scope->parent->name->len;
-                               } else {
-                                       class_name = arg_info->class_name;
-                                       class_name_len = arg_info->class_name_len;
                                }
 
                                smart_str_appendl(&str, class_name, class_name_len);
@@ -403,7 +424,11 @@ static zend_string *zend_get_function_declaration(zend_function *fptr TSRMLS_DC)
                        smart_str_appendc(&str, '$');
 
                        if (arg_info->name) {
-                               smart_str_appendl(&str, arg_info->name, arg_info->name_len);
+                               if (fptr->type == ZEND_INTERNAL_FUNCTION) {
+                                       smart_str_appends(&str, ((zend_internal_arg_info*)arg_info)->name);
+                               } else {
+                                       smart_str_appendl(&str, arg_info->name->val, arg_info->name->len);
+                               }
                        } else {
                                smart_str_appends(&str, "param");
                                smart_str_append_unsigned(&str, i);
index 59e62149f2cd191b02cc4a6c9c6cef0785e41b40..0ab110b52c7100b3d7c8dd849eb28135c1dc43c3 100644 (file)
@@ -370,9 +370,9 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
        }
        if (op_array->arg_info) {
                for (i=0; i<op_array->num_args; i++) {
-                       efree((char*)op_array->arg_info[i].name);
+                       zend_string_release(op_array->arg_info[i].name);
                        if (op_array->arg_info[i].class_name) {
-                               efree((char*)op_array->arg_info[i].class_name);
+                               zend_string_release(op_array->arg_info[i].class_name);
                        }
                }
                efree(op_array->arg_info);
index cb9b7c120e43b94edd2de9d92cf848824275c397..8b622c78e56eadf93cfadf33596aa15303fe2143 100644 (file)
@@ -2666,7 +2666,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
                        zval *p = ZEND_CALL_ARG(call, 1);
 
                        for (i = 0; i < ZEND_CALL_NUM_ARGS(call); ++i) {
-                               zend_verify_arg_type(fbc, i + 1, p, NULL TSRMLS_CC);
+                               zend_verify_internal_arg_type(fbc, i + 1, p TSRMLS_CC);
                                p++;
                        }
                        if (UNEXPECTED(EG(exception) != NULL)) {
index f43fc32e5d08026c0bbaefe5ffd07d1a6d57fb38..cbf1d4b0bdf4dfe878e580e73c8b99d01e73e748 100644 (file)
@@ -538,7 +538,7 @@ static int ZEND_FASTCALL  ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                        zval *p = ZEND_CALL_ARG(call, 1);
 
                        for (i = 0; i < ZEND_CALL_NUM_ARGS(call); ++i) {
-                               zend_verify_arg_type(fbc, i + 1, p, NULL TSRMLS_CC);
+                               zend_verify_internal_arg_type(fbc, i + 1, p TSRMLS_CC);
                                p++;
                        }
                        if (UNEXPECTED(EG(exception) != NULL)) {
index 3e91740a71341189307f0ca63a5c04f4335f961a..f6ade86acf0564bf3e382ee0343d87c3dd8f04d8 100644 (file)
@@ -419,12 +419,10 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
                        zend_accel_store(op_array->arg_info, sizeof(zend_arg_info) * op_array->num_args);
                        for (i = 0; i < op_array->num_args; i++) {
                                if (op_array->arg_info[i].name) {
-//???                                  zend_accel_store_interned_string(op_array->arg_info[i].name, op_array->arg_info[i].name_len + 1);
-                                       zend_accel_store(op_array->arg_info[i].name, op_array->arg_info[i].name_len + 1);
+                                       zend_accel_store_interned_string(op_array->arg_info[i].name);
                                }
                                if (op_array->arg_info[i].class_name) {
-//???                                  zend_accel_store_interned_string(op_array->arg_info[i].class_name, op_array->arg_info[i].class_name_len + 1);
-                                       zend_accel_store(op_array->arg_info[i].class_name, op_array->arg_info[i].class_name_len + 1);
+                                       zend_accel_store_interned_string(op_array->arg_info[i].class_name);
                                }
                        }
                }
index 0a7b8356487ca799deddefa85b3738448af0182b..6a35c5ca9bb0ef86886fb6968954a7f78ebdd679 100644 (file)
@@ -199,12 +199,10 @@ static void zend_persist_op_array_calc_ex(zend_op_array *op_array TSRMLS_DC)
                ADD_DUP_SIZE(op_array->arg_info, sizeof(zend_arg_info) * op_array->num_args);
                for (i = 0; i < op_array->num_args; i++) {
                        if (op_array->arg_info[i].name) {
-//???                          ADD_INTERNED_STRING(op_array->arg_info[i].name, op_array->arg_info[i].name_len + 1);
-                               ADD_SIZE(op_array->arg_info[i].name_len + 1);
+                               ADD_INTERNED_STRING(op_array->arg_info[i].name, 1);
                        }
                        if (op_array->arg_info[i].class_name) {
-//???                          ADD_INTERNED_STRING(op_array->arg_info[i].class_name, op_array->arg_info[i].class_name_len + 1);
-                               ADD_SIZE(op_array->arg_info[i].class_name_len + 1);
+                               ADD_INTERNED_STRING(op_array->arg_info[i].class_name, 1);
                        }
 
                }
index 8e35c1ee9ad063f97b50295f60bc686d773fdfd9..571e08b4c096c98d13615e494507033b3976f283 100644 (file)
@@ -1300,7 +1300,7 @@ int pdo_hash_methods(pdo_dbh_object_t *dbh_obj, int kind TSRMLS_DC)
                if (funcs->arg_info) {
                        zend_internal_function_info *info = (zend_internal_function_info*)funcs->arg_info;
 
-                       ifunc->arg_info = (zend_arg_info*)funcs->arg_info + 1;
+                       ifunc->arg_info = (zend_internal_arg_info*)funcs->arg_info + 1;
                        ifunc->num_args = funcs->num_args;
                        if (info->required_num_args == -1) {
                                ifunc->required_num_args = funcs->num_args;
index e9c59ea86e935a1d010ab4f3d031861c8304503c..7d8f2b43ea301fab168b0cb46859ea5f0a471d66 100644 (file)
@@ -688,7 +688,10 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
                string_printf(str, "<required> ");
        }
        if (arg_info->class_name) {
-               string_printf(str, "%s ", arg_info->class_name);
+               string_printf(str, "%s ",
+                       (fptr->type == ZEND_INTERNAL_FUNCTION) ?
+                       ((zend_internal_arg_info*)arg_info)->class_name :
+                       arg_info->class_name->val);
                if (arg_info->allow_null) {
                        string_printf(str, "or NULL ");
                }
@@ -705,7 +708,10 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
                string_write(str, "...", sizeof("...")-1);
        }
        if (arg_info->name) {
-               string_printf(str, "$%s", arg_info->name);
+               string_printf(str, "$%s",
+                       (fptr->type == ZEND_INTERNAL_FUNCTION) ?
+                       ((zend_internal_arg_info*)arg_info)->name :
+                       arg_info->name->val);
        } else {
                string_printf(str, "$param%d", offset);
        }
@@ -1226,7 +1232,11 @@ static void reflection_parameter_factory(zend_function *fptr, zval *closure_obje
        zval name;
 
        if (arg_info->name) {
-               ZVAL_STRINGL(&name, arg_info->name, arg_info->name_len);
+               if (fptr->type == ZEND_INTERNAL_FUNCTION) {
+                       ZVAL_STRING(&name, ((zend_internal_arg_info*)arg_info)->name);
+               } else {
+                       ZVAL_STR(&name, zend_string_copy(arg_info->name));
+               }
        } else {
                ZVAL_NULL(&name);
        }
@@ -2127,6 +2137,7 @@ ZEND_METHOD(reflection_parameter, __construct)
        int position;
        zend_class_entry *ce = NULL;
        zend_bool is_closure = 0;
+       zend_bool is_invoke = 0;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &reference, &parameter) == FAILURE) {
                return;
@@ -2188,9 +2199,10 @@ ZEND_METHOD(reflection_parameter, __construct)
                                        && (lcname_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
                                        && memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
                                        && (fptr = zend_get_closure_invoke_method(Z_OBJ_P(classref) TSRMLS_CC)) != NULL)
-                               {
+                               {                                       
                                        /* nothing to do. don't set is_closure since is the invoke handler,
--                                         not the closure itself */
+                                          not the closure itself */
+                                       is_invoke = 1;
                                } else if ((fptr = zend_hash_str_find_ptr(&ce->function_table, lcname, lcname_len)) == NULL) {
                                        efree(lcname);
                                        zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
@@ -2243,10 +2255,24 @@ ZEND_METHOD(reflection_parameter, __construct)
 
                position= -1;
                convert_to_string_ex(parameter);
-               for (i = 0; i < fptr->common.num_args; i++) {
-                       if (arg_info[i].name && strcmp(arg_info[i].name, Z_STRVAL_P(parameter)) == 0) {
-                               position= i;
-                               break;
+               if (!is_invoke && fptr->type == ZEND_INTERNAL_FUNCTION) {
+                       for (i = 0; i < fptr->common.num_args; i++) {
+                               if (arg_info[i].name) {
+                                       if (strcmp(((zend_internal_arg_info*)arg_info)[i].name, Z_STRVAL_P(parameter)) == 0) {
+                                               position= i;
+                                               break;
+                                       }
+
+                               }
+                       }
+               } else {
+                       for (i = 0; i < fptr->common.num_args; i++) {
+                               if (arg_info[i].name) {
+                                       if (strcmp(arg_info[i].name->val, Z_STRVAL_P(parameter)) == 0) {
+                                               position= i;
+                                               break;
+                                       }
+                               }
                        }
                }
                if (position == -1) {
@@ -2265,7 +2291,11 @@ ZEND_METHOD(reflection_parameter, __construct)
        }
 
        if (arg_info[position].name) {
-               ZVAL_STRINGL(&name, arg_info[position].name, arg_info[position].name_len);
+               if (fptr->type == ZEND_INTERNAL_FUNCTION) {
+                       ZVAL_STRING(&name, ((zend_internal_arg_info*)arg_info)[position].name);
+               } else {
+                       ZVAL_STR(&name, zend_string_copy(arg_info[position].name));
+               }
        } else {
                ZVAL_NULL(&name);
        }
@@ -2379,14 +2409,24 @@ ZEND_METHOD(reflection_parameter, getClass)
                 * TODO: Think about moving these checks to the compiler or some sort of
                 * lint-mode.
                 */
-               if (0 == zend_binary_strcasecmp(param->arg_info->class_name, param->arg_info->class_name_len, "self", sizeof("self")- 1)) {
+               const char *class_name;
+               size_t class_name_len;
+
+               if (param->fptr->type == ZEND_INTERNAL_FUNCTION) {
+                       class_name = ((zend_internal_arg_info*)param->arg_info)->class_name;
+                       class_name_len = strlen(class_name);
+               } else {
+                       class_name = param->arg_info->class_name->val;
+                       class_name_len = param->arg_info->class_name->len;
+               }
+               if (0 == zend_binary_strcasecmp(class_name, class_name_len, "self", sizeof("self")- 1)) {
                        ce = param->fptr->common.scope;
                        if (!ce) {
                                zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
                                        "Parameter uses 'self' as type hint but function is not a class member!");
                                return;
                        }
-               } else if (0 == zend_binary_strcasecmp(param->arg_info->class_name, param->arg_info->class_name_len, "parent", sizeof("parent")- 1)) {
+               } else if (0 == zend_binary_strcasecmp(class_name, class_name_len, "parent", sizeof("parent")- 1)) {
                        ce = param->fptr->common.scope;
                        if (!ce) {
                                zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
@@ -2400,12 +2440,16 @@ ZEND_METHOD(reflection_parameter, getClass)
                        }
                        ce = ce->parent;
                } else {
-                       zend_string *name = zend_string_init(param->arg_info->class_name, param->arg_info->class_name_len, 0);
-                       ce = zend_lookup_class(name TSRMLS_CC);
-                       zend_string_release(name);
+                       if (param->fptr->type == ZEND_INTERNAL_FUNCTION) {
+                               zend_string *name = zend_string_init(class_name, class_name_len, 0);
+                               ce = zend_lookup_class(name TSRMLS_CC);
+                               zend_string_release(name);
+                       } else {
+                               ce = zend_lookup_class(param->arg_info->class_name TSRMLS_CC);
+                       }
                        if (!ce) {
                                zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
-                                       "Class %s does not exist", param->arg_info->class_name);
+                                       "Class %s does not exist", class_name);
                                return;
                        }
                }
@@ -3347,9 +3391,8 @@ static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value
        zend_property_info *prop_info;
        zval *prop, prop_copy;
        zend_string *key;
-       zend_ulong num_index;
 
-       ZEND_HASH_FOREACH_KEY_PTR(&ce->properties_info, num_index, key, prop_info) {
+       ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
                if (((prop_info->flags & ZEND_ACC_SHADOW) &&
                     prop_info->ce != ce) ||
                    ((prop_info->flags & ZEND_ACC_PROTECTED) &&