From 49efcd4f276262d4a99c1deafc1375ec35c7b29b Mon Sep 17 00:00:00 2001 From: Marcus Boerger Date: Thu, 18 Dec 2003 20:07:30 +0000 Subject: [PATCH] Fixed bug #24837 Incorrect behaviour of PPP using foreach. --- NEWS | 1 + Zend/zend_execute.c | 35 +++++++++++++++++++++++++--------- Zend/zend_object_handlers.c | 38 +++++++++++++++++++++++++++++-------- Zend/zend_object_handlers.h | 2 ++ 4 files changed, 59 insertions(+), 17 deletions(-) diff --git a/NEWS b/NEWS index efae82976e..4d2c049352 100644 --- a/NEWS +++ b/NEWS @@ -52,6 +52,7 @@ PHP NEWS has no properties (NULL hashtable)). (Wez) - Fixed bug #25664 (COM crashes when calling a Delphi implementations of ITypeInfo). (Wez) +- Fixed bug #24837 (Incorrect behaviour of PPP using foreach). (Marcus) - Fixed bug #24693 (Allow session.use_trans_sid to be enabled/disabled from inside the script). (Ilia) - Fixed bug #24394 (Serializing cross-referenced objects causes segfault). diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 1eb9e6e7f2..55df3d81d2 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -3639,12 +3639,33 @@ int zend_fe_fetch_handler(ZEND_OPCODE_HANDLER_ARGS) case ZEND_ITER_PLAIN_ARRAY: /* good old fashioned foreach on an array */ fe_ht = HASH_OF(array); - if (zend_hash_get_current_data(fe_ht, (void **) &value)==FAILURE) { - /* reached end of iteration */ - EX(opline) = op_array->opcodes+EX(opline)->op2.u.opline_num; - return 0; /* CHECK_ME */ + if (Z_TYPE_P(array) == IS_OBJECT) { + char *class_name, *prop_name; + zend_object *zobj = zend_objects_get_address(array TSRMLS_CC); + + do { + if (zend_hash_get_current_data(fe_ht, (void **) &value)==FAILURE) { + /* reached end of iteration */ + EX(opline) = op_array->opcodes+EX(opline)->op2.u.opline_num; + return 0; /* CHECK_ME */ + } + key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL); + + zend_hash_move_forward(fe_ht); + } while (zend_check_property_access(zobj, str_key TSRMLS_CC) != SUCCESS); + unmangle_property_name(str_key, &class_name, &prop_name); + str_key_len = strlen(prop_name); + str_key = estrndup(prop_name, str_key_len); + str_key_len++; + } else { + if (zend_hash_get_current_data(fe_ht, (void **) &value)==FAILURE) { + /* reached end of iteration */ + EX(opline) = op_array->opcodes+EX(opline)->op2.u.opline_num; + return 0; /* CHECK_ME */ + } + key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 1, NULL); + zend_hash_move_forward(fe_ht); } - key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 1, NULL); break; case ZEND_ITER_OBJECT: @@ -3696,10 +3717,6 @@ int zend_fe_fetch_handler(ZEND_OPCODE_HANDLER_ARGS) } zend_hash_index_update(result->value.ht, 1, &key, sizeof(zval *), NULL); - if (!iter) { - zend_hash_move_forward(fe_ht); - } - NEXT_OPCODE(); } diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index ee947ecfd9..1e9e35f4a4 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -155,7 +155,7 @@ static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_D } -static inline int zend_verify_property_access(zend_property_info *property_info, zend_class_entry *ce TSRMLS_DC) +static int zend_verify_property_access(zend_property_info *property_info, zend_class_entry *ce TSRMLS_DC) { switch (property_info->flags & ZEND_ACC_PPP_MASK) { case ZEND_ACC_PUBLIC: @@ -169,7 +169,7 @@ static inline int zend_verify_property_access(zend_property_info *property_info, } return 0; case ZEND_ACC_PRIVATE: - if (ce==EG(scope)) { + if (ce==EG(scope) && EG(scope)) { return 1; } else { return 0; @@ -192,7 +192,7 @@ static inline zend_bool is_derived_class(zend_class_entry *child_class, zend_cla return 0; } -static inline zend_property_info *zend_get_property_info(zend_object *zobj, zval *member TSRMLS_DC) +static inline zend_property_info *zend_get_property_info(zend_object *zobj, zval *member, int silent TSRMLS_DC) { zend_property_info *property_info = NULL; zend_property_info *scope_property_info; @@ -224,6 +224,9 @@ static inline zend_property_info *zend_get_property_info(zend_object *zobj, zval } else if (property_info) { if (denied_access) { /* Information was available, but we were denied access. Error out. */ + if (silent) { + return NULL; + } zend_error(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), zobj->ce->name, Z_STRVAL_P(member)); } else { /* fall through, return property_info... */ @@ -239,6 +242,25 @@ static inline zend_property_info *zend_get_property_info(zend_object *zobj, zval } +ZEND_API int zend_check_property_access(zend_object *zobj, char *prop_info_name TSRMLS_DC) +{ + zend_property_info *property_info; + char *class_name, *prop_name; + zval member; + + unmangle_property_name(prop_info_name, &class_name, &prop_name); + ZVAL_STRING(&member, prop_name, 0); + property_info = zend_get_property_info(zobj, &member, 1 TSRMLS_CC); + if (!property_info) { + return FAILURE; + } + if (prop_info_name[0] == '\0' && prop_info_name[1] != '*' && !(property_info->flags & ZEND_ACC_PRIVATE)) { + /* we we're looking for a private prop but found a non private one of the same name */ + return FAILURE; + } + return zend_verify_property_access(property_info, zobj->ce TSRMLS_CC) ? SUCCESS : FAILURE; +} + zval *zend_std_read_property(zval *object, zval *member, zend_bool silent TSRMLS_DC) { zend_object *zobj; @@ -260,7 +282,7 @@ zval *zend_std_read_property(zval *object, zval *member, zend_bool silent TSRMLS fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member)); #endif - property_info = zend_get_property_info(zobj, member TSRMLS_CC); + property_info = zend_get_property_info(zobj, member, 0 TSRMLS_CC); if (zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE) { if (zobj->ce->__get && !zobj->in_get) { @@ -305,7 +327,7 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM member = &tmp_member; } - property_info = zend_get_property_info(zobj, member TSRMLS_CC); + property_info = zend_get_property_info(zobj, member, 0 TSRMLS_CC); if (zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &variable_ptr) == SUCCESS) { if (*variable_ptr == value) { @@ -425,7 +447,7 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC fprintf(stderr, "Ptr object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member)); #endif - property_info = zend_get_property_info(zobj, member TSRMLS_CC); + property_info = zend_get_property_info(zobj, member, 0 TSRMLS_CC); if (zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE) { zval *new_zval; @@ -464,7 +486,7 @@ static void zend_std_unset_property(zval *object, zval *member TSRMLS_DC) member = &tmp_member; } - property_info = zend_get_property_info(zobj, member TSRMLS_CC); + property_info = zend_get_property_info(zobj, member, 0 TSRMLS_CC); zend_hash_del(zobj->properties, property_info->name, property_info->name_length+1); if (member == &tmp_member) { @@ -841,7 +863,7 @@ static int zend_std_has_property(zval *object, zval *member, int check_empty TSR fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member)); #endif - property_info = zend_get_property_info(zobj, member TSRMLS_CC); + property_info = zend_get_property_info(zobj, member, 0 TSRMLS_CC); if (zend_hash_find(zobj->properties, property_info->name, property_info->name_length+1, (void **) &value) == SUCCESS) { if (check_empty) { diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index 64ae400585..d1478af888 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -127,6 +127,8 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty ZEND_API int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope); +ZEND_API int zend_check_property_access(zend_object *zobj, char *prop_info_name TSRMLS_DC); + #endif /* -- 2.50.1