]> granicus.if.org Git - php/commitdiff
Reimplement PPP properties
authorZeev Suraski <zeev@php.net>
Tue, 4 Feb 2003 12:12:34 +0000 (12:12 +0000)
committerZeev Suraski <zeev@php.net>
Tue, 4 Feb 2003 12:12:34 +0000 (12:12 +0000)
12 files changed:
Zend/zend.c
Zend/zend.h
Zend/zend_API.c
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_globals.h
Zend/zend_hash.c
Zend/zend_hash.h
Zend/zend_object_handlers.c
Zend/zend_opcode.c
Zend/zend_ts_hash.c
Zend/zend_ts_hash.h

index a23255552219e77bae12e9a07da5f8e860478eb6..b3306ed736878b815eefbdb0e9053455065fdf3c 100644 (file)
@@ -378,8 +378,7 @@ static void register_standard_class(void)
        zend_standard_class_def->name = zend_strndup("stdClass", zend_standard_class_def->name_length);
        zend_standard_class_def->parent = NULL;
        zend_hash_init_ex(&zend_standard_class_def->default_properties, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
-       zend_hash_init_ex(&zend_standard_class_def->private_properties, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
-       zend_hash_init_ex(&zend_standard_class_def->protected_properties, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
+       zend_hash_init_ex(&zend_standard_class_def->default_properties_info, 0, NULL, (dtor_func_t) zend_destroy_property_info, 1, 0);
        zend_standard_class_def->static_members = (HashTable *) malloc(sizeof(HashTable));
        zend_hash_init_ex(zend_standard_class_def->static_members, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
        zend_hash_init_ex(&zend_standard_class_def->constants_table, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
index 38d7d21e13de05138780bc3925c249edb1d193f9..4085bcd92d4d3cbf42fb5826b2b346c884a2bb51 100644 (file)
@@ -303,8 +303,7 @@ struct _zend_class_entry {
 
        HashTable function_table;
        HashTable default_properties;
-       HashTable private_properties; /* This is only needed at compile-time */
-       HashTable protected_properties; /* This is only needed at compile-time */
+       HashTable default_properties_info;
        HashTable class_table;
        HashTable *static_members;
        HashTable constants_table;
index c05e5a05d8e9b075c1a9da5ba48de661366b27f3..d99a2c40e2ec40d5494cf7f48cd06ddfb504418c 100644 (file)
@@ -1379,8 +1379,7 @@ ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_c
        class_entry->constants_updated = 0;
        class_entry->ce_flags = 0;
        zend_hash_init(&class_entry->default_properties, 0, NULL, ZVAL_PTR_DTOR, 1);
-       zend_hash_init(&class_entry->private_properties, 0, NULL, ZVAL_PTR_DTOR, 1);
-       zend_hash_init(&class_entry->protected_properties, 0, NULL, ZVAL_PTR_DTOR, 1);
+       zend_hash_init(&class_entry->default_properties_info, 0, NULL, NULL, 1);
        class_entry->static_members = (HashTable *) malloc(sizeof(HashTable));
        zend_hash_init(class_entry->static_members, 0, NULL, ZVAL_PTR_DTOR, 1);
        zend_hash_init(&class_entry->constants_table, 0, NULL, ZVAL_PTR_DTOR, 1);
index 07164f265cfa6f47e5a0387b46ca5de3df0cd17c..d33b1d8b852be24bb784ac10a66ce0eb6411e887 100644 (file)
@@ -1564,11 +1564,16 @@ static void do_inherit_method(zend_function *function)
 }
 
 
-static zend_bool do_inherit_method_check(zend_function *child, zend_function *parent)
+static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_function *parent, zend_hash_key *hash_key, void *pData)
 {
-       zend_uint child_flags  = child->common.fn_flags;
+       zend_uint child_flags;
        zend_uint parent_flags = parent->common.fn_flags;
+       zend_function *child;
 
+       if (zend_hash_quick_find(child_function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child)==FAILURE) {
+               return 1; /* method doesn't exist in child, copy from parent */
+       }
+       child_flags     = child->common.fn_flags;
        /* You cannot change from static to non static and vice versa.
         */
        if ((child_flags & ZEND_ACC_STATIC) != (parent_flags & ZEND_ACC_STATIC)) {
@@ -1602,18 +1607,38 @@ static zend_bool do_inherit_method_check(zend_function *child, zend_function *pa
 }
 
 
+static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_property_info *parent_info, zend_hash_key *hash_key, zend_class_entry *ce)
+{
+       zend_property_info *child_info;
+       zend_class_entry *parent_ce = ce->parent;
+
+       if (parent_info->flags & ZEND_ACC_PRIVATE) {
+               return 0; /* don't copy access information to child */
+       }
+
+       if (zend_hash_quick_find(&ce->default_properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
+               if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) {
+                       zend_error(E_COMPILE_ERROR, "Access level to %s::$%s must be %s (as in class %s)%s", ce->name, hash_key->arKey, zend_visibility_string(parent_info->flags), parent_ce->name, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
+               }
+               return 0;       /* Don't copy from parent */
+       } else {
+               return 1;       /* Copy from parent */
+       }
+}
+
+
 void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce)
 {
-       zval *tmp;
+       ce->parent = parent_ce;
 
-       /* Perform inheritance */
-       zend_hash_merge(&ce->default_properties, &parent_ce->default_properties, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0);
+       /* Inherit properties */
+       zend_hash_merge(&ce->default_properties, &parent_ce->default_properties, (void (*)(void *)) zval_add_ref, NULL, sizeof(zval *), 0);
+       zend_hash_merge_ex(&ce->default_properties_info, &parent_ce->default_properties_info, (copy_ctor_func_t) zend_duplicate_property_info, sizeof(zend_property_info), (merge_checker_func_t) do_inherit_property_access_check, ce);
 
        /* STATIC_MEMBERS_FIXME */
 /*     zend_hash_merge(ce->static_members, parent_ce->static_members, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0); */
-       zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0);
-       zend_hash_merge_ex(&ce->function_table, &parent_ce->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (zend_bool (*)(void *, void *)) do_inherit_method_check);
-       ce->parent = parent_ce;
+       zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, (void (*)(void *)) zval_add_ref, NULL, sizeof(zval *), 0);
+       zend_hash_merge_ex(&ce->function_table, &parent_ce->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (merge_checker_func_t) do_inherit_method_check, NULL);
        do_inherit_parent_constructor(ce);
 }
 
@@ -1635,8 +1660,7 @@ static void create_class(HashTable *class_table, char *name, int name_length, ze
        zend_hash_init(&new_class_entry->function_table, 10, NULL, ZEND_FUNCTION_DTOR, 0);
        zend_hash_init(&new_class_entry->class_table, 10, NULL, ZEND_CLASS_DTOR, 0);
        zend_hash_init(&new_class_entry->default_properties, 10, NULL, ZVAL_PTR_DTOR, 0);
-       zend_hash_init(&new_class_entry->private_properties, 10, NULL, ZVAL_PTR_DTOR, 0);
-       zend_hash_init(&new_class_entry->protected_properties, 10, NULL, ZVAL_PTR_DTOR, 0);
+       zend_hash_init(&new_class_entry->default_properties_info, 10, NULL, NULL, 0);
        ALLOC_HASHTABLE(new_class_entry->static_members);
        zend_hash_init(new_class_entry->static_members, 10, NULL, ZVAL_PTR_DTOR, 0);
        zend_hash_init(&new_class_entry->constants_table, 10, NULL, ZVAL_PTR_DTOR, 0);
@@ -1780,8 +1804,7 @@ ZEND_API int do_bind_inherited_class(zend_op *opline, HashTable *function_table,
                ce->refcount--;
                zend_hash_destroy(&ce->function_table);
                zend_hash_destroy(&ce->default_properties);
-               zend_hash_destroy(&ce->private_properties);
-               zend_hash_destroy(&ce->protected_properties);
+               zend_hash_destroy(&ce->default_properties_info);
                zend_hash_destroy(ce->static_members);
                zend_hash_destroy(&ce->constants_table);
                return FAILURE;
@@ -2117,8 +2140,7 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
        zend_hash_init(&new_class_entry->function_table, 10, NULL, ZEND_FUNCTION_DTOR, 0);
        zend_hash_init(&new_class_entry->class_table, 10, NULL, ZEND_CLASS_DTOR, 0);
        zend_hash_init(&new_class_entry->default_properties, 10, NULL, ZVAL_PTR_DTOR, 0);
-       zend_hash_init(&new_class_entry->private_properties, 10, NULL, ZVAL_PTR_DTOR, 0);
-       zend_hash_init(&new_class_entry->protected_properties, 10, NULL, ZVAL_PTR_DTOR, 0);
+       zend_hash_init(&new_class_entry->default_properties_info, 10, NULL, NULL, 0);
        ALLOC_HASHTABLE(new_class_entry->static_members);
        zend_hash_init(new_class_entry->static_members, 10, NULL, ZVAL_PTR_DTOR, 0);
        zend_hash_init(&new_class_entry->constants_table, 10, NULL, ZVAL_PTR_DTOR, 0);
@@ -2190,6 +2212,7 @@ void mangle_property_name(char **dest, int *dest_length, char *src1, int src1_le
 void zend_do_declare_property(znode *var_name, znode *value TSRMLS_DC)
 {
        zval *property;
+       zend_property_info property_info;
 
        ALLOC_ZVAL(property);
 
@@ -2208,51 +2231,38 @@ void zend_do_declare_property(znode *var_name, znode *value TSRMLS_DC)
        }
 
        switch (CG(access_type)) {
-               case ZEND_ACC_PRIVATE:
-                       {
+               case ZEND_ACC_PRIVATE: {
                                char *priv_name;
                                int priv_name_length;
-                                
+
                                mangle_property_name(&priv_name, &priv_name_length, CG(active_class_entry)->name, CG(active_class_entry)->name_length, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len);
                                zend_hash_update(&CG(active_class_entry)->default_properties, priv_name, priv_name_length+1, &property, sizeof(zval *), NULL);
-                               efree(priv_name);
-
-                               property->refcount++;
-                                
-                               zend_hash_update(&CG(active_class_entry)->private_properties, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL);
-                               break;
+                               property_info.name = priv_name;
+                               property_info.name_length = priv_name_length;
                        }
-               case ZEND_ACC_PROTECTED:
-                       {
+                       break;
+               case ZEND_ACC_PROTECTED: {
                                char *prot_name;
                                int prot_name_length;
-                               zval **found = NULL;
-                                
-                               if (CG(active_class_entry)->parent) {
-                                       zend_hash_find(&CG(active_class_entry)->parent->protected_properties, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, (void **) &found);
-                               }
 
                                mangle_property_name(&prot_name, &prot_name_length, "*", 1, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len);
-                               /* If we don't have a value and it exists in our parent then use the parent's value */
-                               if (!value && found) {
-                                       (*found)->refcount++;
-                                       zend_hash_update(&CG(active_class_entry)->default_properties, prot_name, prot_name_length+1, found, sizeof(zval *), NULL);
-                                       (*found)->refcount++;
-                                       zend_hash_update(&CG(active_class_entry)->protected_properties, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, found, sizeof(zval *), NULL);
-                                       zval_ptr_dtor(&property);
-                               } else {
-                                       zend_hash_update(&CG(active_class_entry)->default_properties, prot_name, prot_name_length+1, &property, sizeof(zval *), NULL);
-                                       property->refcount++;
-                                       zend_hash_update(&CG(active_class_entry)->protected_properties, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL);
-                               }
-                               efree(prot_name);
-                               break;
+                               zend_hash_update(&CG(active_class_entry)->default_properties, prot_name, prot_name_length+1, &property, sizeof(zval *), NULL);
+                               property_info.name = prot_name;
+                               property_info.name_length = prot_name_length;
                        }
+                       break;
                case ZEND_ACC_PUBLIC:
                        zend_hash_update(&CG(active_class_entry)->default_properties, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL);
+                       property_info.name = var_name->u.constant.value.str.val;
+                       property_info.name_length = var_name->u.constant.value.str.len;
                        break;
        }
-       FREE_PNODE(var_name);
+       property_info.flags = CG(access_type);
+       property_info.h = zend_get_hash_value(property_info.name, property_info.name_length+1);
+
+       zend_hash_update(&CG(active_class_entry)->default_properties_info, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property_info, sizeof(zend_property_info), NULL);
+
+       /*FREE_PNODE(var_name);*/
 }
 
 
@@ -2317,28 +2327,6 @@ void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS
                                        opline_ptr->opcode = ZEND_FETCH_OBJ_FUNC_ARG;
                                        break;
                        }
-
-                       if (CG(active_class_entry) && (opline_ptr->op2.op_type == IS_CONST)) {
-                               if (zend_hash_exists(&CG(active_class_entry)->private_properties, opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len+1)) {
-                                       char *priv_name;
-                                       int priv_name_length;
-                                        
-                                       mangle_property_name(&priv_name, &priv_name_length, CG(active_class_entry)->name, CG(active_class_entry)->name_length, opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len);
-
-                                       STR_FREE(opline_ptr->op2.u.constant.value.str.val);
-                                       opline_ptr->op2.u.constant.value.str.val = priv_name;
-                                       opline_ptr->op2.u.constant.value.str.len = priv_name_length;
-                               } else if (zend_hash_exists(&CG(active_class_entry)->protected_properties, opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len+1)) {
-                                       char *prot_name;
-                                       int prot_name_length;
-                                        
-                                       mangle_property_name(&prot_name, &prot_name_length, "*", 1, opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len);
-
-                                       STR_FREE(opline_ptr->op2.u.constant.value.str.val);
-                                       opline_ptr->op2.u.constant.value.str.val = prot_name;
-                                       opline_ptr->op2.u.constant.value.str.len = prot_name_length;
-                               }
-                       }
                        *result = opline_ptr->result;
                        return;
                }
@@ -2353,34 +2341,6 @@ void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS
        opline.op2 = *property;
        *result = opline.result;
 
-       if (CG(in_clone_method)) {
-               if ((opline_ptr->op1.op_type == IS_CONST) && (opline_ptr->op1.u.constant.type == IS_STRING) &&
-                       (opline_ptr->op1.u.constant.value.str.len == (sizeof("that")-1)) &&
-                       !memcmp(opline_ptr->op1.u.constant.value.str.val, "that", sizeof("that"))) {
-                       if (CG(active_class_entry) && (opline.op2.op_type == IS_CONST)) {
-                               if (zend_hash_exists(&CG(active_class_entry)->private_properties, opline.op2.u.constant.value.str.val, opline.op2.u.constant.value.str.len+1)) {
-                                       char *priv_name;
-                                       int priv_name_length;
-                                
-                                       mangle_property_name(&priv_name, &priv_name_length, CG(active_class_entry)->name, CG(active_class_entry)->name_length, opline.op2.u.constant.value.str.val, opline.op2.u.constant.value.str.len);
-
-                                       STR_FREE(opline.op2.u.constant.value.str.val);
-                                       opline.op2.u.constant.value.str.val = priv_name;
-                                       opline.op2.u.constant.value.str.len = priv_name_length;
-                               } else if (zend_hash_exists(&CG(active_class_entry)->protected_properties, opline.op2.u.constant.value.str.val, opline.op2.u.constant.value.str.len+1)) {
-                                       char *prot_name;
-                                       int prot_name_length;
-                                
-                                       mangle_property_name(&prot_name, &prot_name_length, "*", 1, opline.op2.u.constant.value.str.val, opline.op2.u.constant.value.str.len);
-
-                                       STR_FREE(opline.op2.u.constant.value.str.val);
-                                       opline.op2.u.constant.value.str.val = prot_name;
-                                       opline.op2.u.constant.value.str.len = prot_name_length;
-                               }
-                       }
-               }
-       }
-
        zend_llist_add_element(fetch_list_ptr, &opline);
 }
 
@@ -3213,6 +3173,19 @@ int zendlex(znode *zendlval TSRMLS_DC)
        return retval;
 }
 
+
+void zend_duplicate_property_info(zend_property_info *property_info)
+{
+       property_info->name = estrndup(property_info->name, property_info->name_length);
+}
+
+
+void zend_destroy_property_info(zend_property_info *property_info)
+{
+       efree(property_info->name);
+}
+
+
 /*
  * Local variables:
  * tab-width: 4
index 5f36b7b98dbf2f4bbc6ed5ea779bda498a1d1a41..fa54846ed1b4418b04927039e8423b245281a736 100644 (file)
@@ -102,6 +102,15 @@ typedef struct _zend_brk_cont_element {
 
 char *zend_visibility_string(zend_uint fn_flags);
 
+
+typedef struct _zend_property_info {
+       zend_uint flags;
+       char *name;
+       int name_length;
+       ulong h;
+} zend_property_info;
+
+
 struct _zend_op_array {
        zend_uchar type;                        /* MUST be the first element of this struct! */
 
@@ -435,6 +444,10 @@ ZEND_API void destroy_zend_function(zend_function *function);
 ZEND_API void destroy_zend_class(zend_class_entry **pce);
 void zend_class_add_ref(zend_class_entry **ce);
 
+
+void zend_duplicate_property_info(zend_property_info *property_info);
+void zend_destroy_property_info(zend_property_info *property_info);
+
 #define ZEND_FUNCTION_DTOR (void (*)(void *)) destroy_zend_function
 #define ZEND_CLASS_DTOR (void (*)(void *)) destroy_zend_class
 
index 07bd704a7e4211ab326add7e662562b0a87ce694..c8b83303481865ae29ce9ad986d6afe06aa3a43e 100644 (file)
@@ -126,7 +126,7 @@ struct _zend_compiler_globals {
 
        zend_llist import_commands;
 
-       int access_type;
+       zend_uint access_type;
 };
 
 
index 59a2e9d4f3b622f764951f547e7763a4bd3c9bea..d9a72724268840a9a584bf1f38fbf3ea25e3e159 100644 (file)
@@ -288,11 +288,8 @@ ZEND_API int zend_hash_quick_add_or_update(HashTable *ht, char *arKey, uint nKey
 
        IS_CONSISTENT(ht);
 
-       if (nKeyLength <= 0) {
-#if ZEND_DEBUG
-               ZEND_PUTS("zend_hash_update: Can't put in empty key\n");
-#endif
-               return FAILURE;
+       if (nKeyLength == 0) {
+               return zend_hash_index_update(ht, h, pData, nDataSize, pDest);
        }
 
        nIndex = h & ht->nTableMask;
@@ -819,30 +816,30 @@ ZEND_API void zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_fu
 }
 
 
-ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, uint size, zend_bool (*pReplaceOrig)(void *orig, void *p_new))
+static int zend_hash_replace_checker_wrapper(HashTable *target, void *source_data, Bucket *p, void *pParam, merge_checker_func_t merge_checker_func)
+{
+       zend_hash_key hash_key;
+
+       hash_key.arKey = p->arKey;
+       hash_key.nKeyLength = p->nKeyLength;
+       hash_key.h = p->h;
+       return merge_checker_func(target, source_data, &hash_key, pParam);
+}
+
+
+ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, uint size, merge_checker_func_t pMergeSource, void *pParam)
 {
        Bucket *p;
        void *t;
-       void *pOrig;
 
        IS_CONSISTENT(source);
        IS_CONSISTENT(target);
 
     p = source->pListHead;
        while (p) {
-               if (p->nKeyLength>0) {
-                       if (zend_hash_find(target, p->arKey, p->nKeyLength, &pOrig)==FAILURE
-                               || pReplaceOrig(pOrig, p->pData)) {
-                               if (zend_hash_update(target, p->arKey, p->nKeyLength, p->pData, size, &t)==SUCCESS && pCopyConstructor) {
-                                       pCopyConstructor(t);
-                               }
-                       }
-               } else {
-                       if (zend_hash_index_find(target, p->h, &pOrig)==FAILURE
-                               || pReplaceOrig(pOrig, p->pData)) {
-                               if (zend_hash_index_update(target, p->h, p->pData, size, &t)==SUCCESS && pCopyConstructor) {
-                                       pCopyConstructor(t);
-                               }
+               if (zend_hash_replace_checker_wrapper(target, p->pData, p, pParam, pMergeSource)) {
+                       if (zend_hash_quick_update(target, p->arKey, p->nKeyLength, p->h, p->pData, size, &t)==SUCCESS && pCopyConstructor) {
+                               pCopyConstructor(t);
                        }
                }
                p = p->pListNext;
@@ -851,10 +848,8 @@ ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor
 }
 
 
-ZEND_API ulong zend_get_hash_value(HashTable *ht, char *arKey, uint nKeyLength)
+ZEND_API ulong zend_get_hash_value(char *arKey, uint nKeyLength)
 {
-       IS_CONSISTENT(ht);
-
        return zend_inline_hash_func(arKey, nKeyLength);
 }
 
@@ -895,6 +890,10 @@ ZEND_API int zend_hash_quick_find(HashTable *ht, char *arKey, uint nKeyLength, u
        uint nIndex;
        Bucket *p;
 
+       if (nKeyLength==0) {
+               return zend_hash_index_find(ht, h, pData);
+       }
+
        IS_CONSISTENT(ht);
 
        nIndex = h & ht->nTableMask;
index b6330491dab48bee8c87016f8b473e99919c5266..dc7961e4a713c3b1c0f37acc9c0b7182325519db 100644 (file)
@@ -75,6 +75,16 @@ typedef struct _hashtable {
 #endif
 } HashTable;
 
+
+typedef struct _zend_hash_key {
+       char *arKey;
+       uint nKeyLength;
+       ulong h;
+} zend_hash_key;
+
+
+typedef int (*merge_checker_func_t)(HashTable *target_ht, void *source_data, zend_hash_key *hash_key, void *pParam);
+
 typedef Bucket* HashPosition;
 
 BEGIN_EXTERN_C()
@@ -113,12 +123,6 @@ ZEND_API int zend_hash_add_empty_element(HashTable *ht, char *arKey, uint nKeyLe
 #define ZEND_HASH_APPLY_REMOVE                         1<<0
 #define ZEND_HASH_APPLY_STOP                           1<<1
 
-typedef struct _zend_hash_key {
-       char *arKey;
-       uint nKeyLength;
-       ulong h;
-} zend_hash_key;
-
 
 typedef int (*apply_func_t)(void *pDest TSRMLS_DC);
 typedef int (*apply_func_arg_t)(void *pDest, void *argument TSRMLS_DC);
@@ -146,7 +150,7 @@ ZEND_API int zend_hash_del_key_or_index(HashTable *ht, char *arKey, uint nKeyLen
 #define zend_hash_index_del(ht, h) \
                zend_hash_del_key_or_index(ht, NULL, 0, h, HASH_DEL_INDEX)
 
-ZEND_API ulong zend_get_hash_value(HashTable *ht, char *arKey, uint nKeyLength);
+ZEND_API ulong zend_get_hash_value(char *arKey, uint nKeyLength);
 
 /* Data retreival */
 ZEND_API int zend_hash_find(HashTable *ht, char *arKey, uint nKeyLength, void **pData);
@@ -185,7 +189,7 @@ ZEND_API void zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos
 /* Copying, merging and sorting */
 ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size);
 ZEND_API void zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, int overwrite);
-ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, uint size, zend_bool (*pReplaceOrig)(void *orig, void *p_new));
+ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, uint size, merge_checker_func_t pMergeSource, void *pParam);
 ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func, compare_func_t compare_func, int renumber TSRMLS_DC);
 ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered TSRMLS_DC);
 ZEND_API int zend_hash_minmax(HashTable *ht, compare_func_t compar, int flag, void **pData TSRMLS_DC);
index 4ea73501a21c793a0844857e4df8f307b4726a80..a635ce381012a816b8984f3b52ec3c460b5b1e6f 100644 (file)
@@ -152,12 +152,44 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_D
        return ret;
 }
 
+
+inline int zend_verify_property_access(zend_property_info *property_info, zend_object *zobj TSRMLS_DC)
+{
+       switch (property_info->flags & ZEND_ACC_PPP_MASK) {
+               case ZEND_ACC_PUBLIC:
+                       return 1;
+               case ZEND_ACC_PRIVATE:
+                       if (zobj->ce == EG(scope)) {
+                               return 1;
+                       } else {
+                               return 0;
+                       }
+                       break;
+               case ZEND_ACC_PROTECTED: {
+                               zend_class_entry *ce = zobj->ce;
+
+                               while (ce) {
+                                       if (ce==EG(scope)) {
+                                               return 1;
+                                       }
+                                       ce = ce->parent;
+                               }
+                               return 0;
+                       }                       
+                       break;
+       }
+       return 0;
+}
+
+
 zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC)
 {
        zend_object *zobj;
        zval tmp_member;
        zval **retval;
        zval *rv = NULL;
+       zend_property_info *property_info;
+       zend_property_info std_property_info;
        
        zobj = Z_OBJ_P(object);
 
@@ -171,8 +203,23 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC)
 #if DEBUG_OBJECT_HANDLERS
        fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member));
 #endif                 
-       
-       if (zend_hash_find(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &retval) == FAILURE) {
+
+       if (zend_hash_find(&zobj->ce->default_properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &property_info)==FAILURE) {
+               std_property_info.flags = ZEND_ACC_PUBLIC;
+               std_property_info.name = Z_STRVAL_P(member);
+               std_property_info.name_length = Z_STRLEN_P(member);
+               std_property_info.h = zend_get_hash_value(std_property_info.name, std_property_info.name_length+1);
+               property_info = &std_property_info;
+       }
+
+#if DEBUG_OBJECT_HANDLERS
+       zend_printf("Access type for %s::%s is %s\n", zobj->ce->name, Z_STRVAL_P(member), zend_visibility_string(property_info->flags));
+#endif
+       if (!zend_verify_property_access(property_info, zobj TSRMLS_CC)) {
+               zend_error(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), zobj->ce->name, Z_STRVAL_P(member));
+       }
+
+       if (zend_hash_find(zobj->properties, property_info->name, property_info->name_length+1, (void **) &retval) == FAILURE) {
                if (zobj->ce->__get && !zobj->in_get) {
                        /* have getter - try with it! */
                        zobj->in_get = 1; /* prevent circular getting */
@@ -213,12 +260,15 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC)
        return *retval;
 }
 
+
 static void zend_std_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
 {
        zend_object *zobj;
        zval tmp_member;
        zval **variable_ptr;
        int setter_done = 0;
+       zend_property_info *property_info;
+       zend_property_info std_property_info;
        
        zobj = Z_OBJ_P(object);
 
@@ -229,7 +279,23 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM
                member = &tmp_member;
        }
 
-       if (zend_hash_find(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &variable_ptr) == SUCCESS) {
+       if (zend_hash_find(&zobj->ce->default_properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &property_info)==FAILURE) {
+               std_property_info.flags = ZEND_ACC_PUBLIC;
+               std_property_info.name = Z_STRVAL_P(member);
+               std_property_info.name_length = Z_STRLEN_P(member);
+               std_property_info.h = zend_get_hash_value(std_property_info.name, std_property_info.name_length+1);
+               property_info = &std_property_info;
+       }
+
+#if DEBUG_OBJECT_HANDLERS
+       zend_printf("Access type for %s::%s is %s\n", zobj->ce->name, Z_STRVAL_P(member), zend_visibility_string(property_info->flags));
+#endif
+
+       if (!zend_verify_property_access(property_info, zobj TSRMLS_CC)) {
+               zend_error(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), zobj->ce->name, Z_STRVAL_P(member));
+       }
+
+       if (zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, std_property_info.h, (void **) &variable_ptr) == SUCCESS) {
                if (*variable_ptr == value) {
                        /* if we already have this value there, we don't actually need to do anything */
                        setter_done = 1;
index 9bf3e7e16e9373a8446d8785ee2a5c59458501e7..2b636771de566e4b3172f12463252ff075c487ab 100644 (file)
@@ -146,8 +146,7 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
        switch (ce->type) {
                case ZEND_USER_CLASS:
                        zend_hash_destroy(&ce->default_properties);
-                       zend_hash_destroy(&ce->private_properties);
-                       zend_hash_destroy(&ce->protected_properties);
+                       zend_hash_destroy(&ce->default_properties_info);
                        zend_hash_destroy(ce->static_members);
                        efree(ce->name);
                        zend_hash_destroy(&ce->function_table);
@@ -158,8 +157,7 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
                        break;
                case ZEND_INTERNAL_CLASS:
                        zend_hash_destroy(&ce->default_properties);
-                       zend_hash_destroy(&ce->private_properties);
-                       zend_hash_destroy(&ce->protected_properties);
+                       zend_hash_destroy(&ce->default_properties_info);
                        zend_hash_destroy(ce->static_members);
                        free(ce->name);
                        zend_hash_destroy(&ce->function_table);
index 74f1f3d6149905141819b2c55ce6350a9b0e29e6..a47dcf4fc5b6c8bb49b73154002152723fdb3841 100644 (file)
@@ -194,7 +194,7 @@ ZEND_API ulong zend_ts_get_hash_value(TsHashTable *ht, char *arKey, uint nKeyLen
        ulong retval;
 
        begin_read(ht);
-       retval = zend_get_hash_value(TS_HASH(ht), arKey, nKeyLength);
+       retval = zend_get_hash_value(arKey, nKeyLength);
        end_read(ht);
 
        return retval;
@@ -273,11 +273,11 @@ ZEND_API void zend_ts_hash_merge(TsHashTable *target, TsHashTable *source, copy_
        end_read(source);
 }
 
-ZEND_API void zend_ts_hash_merge_ex(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, uint size, zend_bool (*pReplaceOrig)(void *orig, void *p_new))
+ZEND_API void zend_ts_hash_merge_ex(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, uint size, merge_checker_func_t pMergeSource, void *pParam)
 {
        begin_read(source);
        begin_write(target);
-       zend_hash_merge_ex(TS_HASH(target), TS_HASH(source), pCopyConstructor, size, pReplaceOrig);
+       zend_hash_merge_ex(TS_HASH(target), TS_HASH(source), pCopyConstructor, size, pMergeSource, pParam);
        end_write(target);
        end_read(source);
 }
index 3cd316ff1be904134432d26a46504c09b09b863e..736d214f889469221807f62032f37940259397a8 100644 (file)
@@ -92,7 +92,7 @@ ZEND_API int zend_ts_hash_index_exists(TsHashTable *ht, ulong h);
 /* Copying, merging and sorting */
 ZEND_API void zend_ts_hash_copy(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size);
 ZEND_API void zend_ts_hash_merge(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, int overwrite);
-ZEND_API void zend_ts_hash_merge_ex(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, uint size, zend_bool (*pReplaceOrig)(void *orig, void *p_new));
+ZEND_API void zend_ts_hash_merge_ex(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, uint size, merge_checker_func_t pMergeSource, void *pParam);
 ZEND_API int zend_ts_hash_sort(TsHashTable *ht, sort_func_t sort_func, compare_func_t compare_func, int renumber TSRMLS_DC);
 ZEND_API int zend_ts_hash_compare(TsHashTable *ht1, TsHashTable *ht2, compare_func_t compar, zend_bool ordered TSRMLS_DC);
 ZEND_API int zend_ts_hash_minmax(TsHashTable *ht, compare_func_t compar, int flag, void **pData TSRMLS_DC);