diff options
author | Zeev Suraski <zeev@php.net> | 2003-02-04 12:12:34 +0000 |
---|---|---|
committer | Zeev Suraski <zeev@php.net> | 2003-02-04 12:12:34 +0000 |
commit | 471947b1885b82f82ba9c338731979c5cc952aec (patch) | |
tree | 1711df79a216628d53d65348f9067bb07f372ce9 /Zend | |
parent | be3908cc8e6e3616b3f2dd5cf11479390cad917b (diff) | |
download | php-git-471947b1885b82f82ba9c338731979c5cc952aec.tar.gz |
Reimplement PPP properties
Diffstat (limited to 'Zend')
-rw-r--r-- | Zend/zend.c | 3 | ||||
-rw-r--r-- | Zend/zend.h | 3 | ||||
-rw-r--r-- | Zend/zend_API.c | 3 | ||||
-rw-r--r-- | Zend/zend_compile.c | 163 | ||||
-rw-r--r-- | Zend/zend_compile.h | 13 | ||||
-rw-r--r-- | Zend/zend_globals.h | 2 | ||||
-rw-r--r-- | Zend/zend_hash.c | 45 | ||||
-rw-r--r-- | Zend/zend_hash.h | 20 | ||||
-rw-r--r-- | Zend/zend_object_handlers.c | 72 | ||||
-rw-r--r-- | Zend/zend_opcode.c | 6 | ||||
-rw-r--r-- | Zend/zend_ts_hash.c | 6 | ||||
-rw-r--r-- | Zend/zend_ts_hash.h | 2 |
12 files changed, 194 insertions, 144 deletions
diff --git a/Zend/zend.c b/Zend/zend.c index a232555522..b3306ed736 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -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); diff --git a/Zend/zend.h b/Zend/zend.h index 38d7d21e13..4085bcd92d 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -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; diff --git a/Zend/zend_API.c b/Zend/zend_API.c index c05e5a05d8..d99a2c40e2 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -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); diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 07164f265c..d33b1d8b85 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -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 diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 5f36b7b98d..fa54846ed1 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -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 diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 07bd704a7e..c8b8330348 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -126,7 +126,7 @@ struct _zend_compiler_globals { zend_llist import_commands; - int access_type; + zend_uint access_type; }; diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 59a2e9d4f3..d9a7272426 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -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; diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index b6330491da..dc7961e4a7 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -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); diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 4ea73501a2..a635ce3810 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -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; diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 9bf3e7e16e..2b636771de 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -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); diff --git a/Zend/zend_ts_hash.c b/Zend/zend_ts_hash.c index 74f1f3d614..a47dcf4fc5 100644 --- a/Zend/zend_ts_hash.c +++ b/Zend/zend_ts_hash.c @@ -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); } diff --git a/Zend/zend_ts_hash.h b/Zend/zend_ts_hash.h index 3cd316ff1b..736d214f88 100644 --- a/Zend/zend_ts_hash.h +++ b/Zend/zend_ts_hash.h @@ -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); |