]> granicus.if.org Git - php/commitdiff
Fixed bug #24837 Incorrect behaviour of PPP using foreach.
authorMarcus Boerger <helly@php.net>
Thu, 18 Dec 2003 20:07:30 +0000 (20:07 +0000)
committerMarcus Boerger <helly@php.net>
Thu, 18 Dec 2003 20:07:30 +0000 (20:07 +0000)
NEWS
Zend/zend_execute.c
Zend/zend_object_handlers.c
Zend/zend_object_handlers.h

diff --git a/NEWS b/NEWS
index efae82976e2783a121d1994260106dc11cf29b47..4d2c049352d298e9f135b030c2cbce1e6e4893dd 100644 (file)
--- 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).
index 1eb9e6e7f25b99549e119b8b2c7a7c193ddb77d7..55df3d81d27528e077d0babdf43eeb5398f575ae 100644 (file)
@@ -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();
 }
 
index ee947ecfd95ed935ea8c67cbcac12c1d3bed940d..1e9e35f4a4c366329b5d2d55acb907566e52290f 100644 (file)
@@ -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) {
index 64ae400585550469f13913997ef49d7f8cd1c7eb..d1478af8889ab39dda2a7dca05dc19b42c0b1f9e 100644 (file)
@@ -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
 
 /*