]> granicus.if.org Git - php/commitdiff
Fixed bug #62059
authorNikita Popov <nikic@php.net>
Sun, 20 Mar 2016 17:17:44 +0000 (18:17 +0100)
committerNikita Popov <nikic@php.net>
Sun, 20 Mar 2016 17:17:44 +0000 (18:17 +0100)
NEWS
ext/spl/spl_array.c
ext/spl/tests/bug62059.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index f7d1c7d93d794f7537bf3f3666cc464018710a2c..3fd121c030032f8b81802030fe36084b1ea19b32 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,7 @@ PHP                                                                        NEWS
   . Fixed bug #71731 (Null coalescing operator and ArrayAccess). (Nikita)
   . Fixed bug #69659 (ArrayAccess, isset() and the offsetExists method).
     (Nikita)
+  . Fixed bug #62059 (ArrayObject and isset are not friends). (Nikita)
 
 - ODBC:
   . Fixed bug #63171 (Script hangs after max_execution_time). (Remi)
index 685dd27092acb70f3613aa6458162916d9a6f6ca..d5cb32606ea4cb4843548ed2f50dbbb3c174976c 100644 (file)
@@ -275,12 +275,11 @@ static zend_object *spl_array_object_clone(zval *zobject)
 }
 /* }}} */
 
-static zval *spl_array_get_dimension_ptr(int check_inherited, zval *object, zval *offset, int type) /* {{{ */
+static zval *spl_array_get_dimension_ptr(int check_inherited, spl_array_object *intern, zval *offset, int type) /* {{{ */
 {
        zval *retval;
        zend_long index;
        zend_string *offset_key;
-       spl_array_object *intern = Z_SPLARRAY_P(object);
        HashTable *ht = spl_array_get_hash_table(intern);
 
        if (!offset || Z_ISUNDEF_P(offset)) {
@@ -382,12 +381,21 @@ num_index:
        }
 } /* }}} */
 
+static int spl_array_has_dimension(zval *object, zval *offset, int check_empty);
+
 static zval *spl_array_read_dimension_ex(int check_inherited, zval *object, zval *offset, int type, zval *rv) /* {{{ */
 {
+       spl_array_object *intern = Z_SPLARRAY_P(object);
        zval *ret;
 
-       if (check_inherited) {
-               spl_array_object *intern = Z_SPLARRAY_P(object);
+       if (check_inherited &&
+                       (intern->fptr_offset_get || (type == BP_VAR_IS && intern->fptr_offset_has))) {
+               if (type == BP_VAR_IS) {
+                       if (!spl_array_has_dimension(object, offset, 0)) {
+                               return &EG(uninitialized_zval);
+                       }
+               }
+
                if (intern->fptr_offset_get) {
                        zval tmp;
                        if (!offset) {
@@ -405,7 +413,8 @@ static zval *spl_array_read_dimension_ex(int check_inherited, zval *object, zval
                        return &EG(uninitialized_zval);
                }
        }
-       ret = spl_array_get_dimension_ptr(check_inherited, object, offset, type);
+
+       ret = spl_array_get_dimension_ptr(check_inherited, intern, offset, type);
 
        /* When in a write context,
         * ZE has to be fooled into thinking this is in a reference set
@@ -879,7 +888,7 @@ static zval *spl_array_get_property_ptr_ptr(zval *object, zval *member, int type
 
        if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0
                && !std_object_handlers.has_property(object, member, 2, NULL)) {
-               return spl_array_get_dimension_ptr(1, object, member, type);
+               return spl_array_get_dimension_ptr(1, intern, member, type);
        }
        return std_object_handlers.get_property_ptr_ptr(object, member, type, cache_slot);
 } /* }}} */
diff --git a/ext/spl/tests/bug62059.phpt b/ext/spl/tests/bug62059.phpt
new file mode 100644 (file)
index 0000000..241dc5a
--- /dev/null
@@ -0,0 +1,70 @@
+--TEST--
+Bug #62059: ArrayObject and isset are not friends
+--FILE--
+<?php
+
+class MyArrayObject1 extends ArrayObject {
+    public function offsetGet($name) {
+        echo "offsetGet($name)\n";
+        return parent::offsetGet($name);
+    }
+    public function offsetExists($name) {
+        echo "offsetExists($name)\n";
+        return parent::offsetExists($name);
+    }
+}
+class MyArrayObject2 extends ArrayObject {
+    public function offsetGet($name) {
+        echo "offsetGet($name)\n";
+        return parent::offsetGet($name);
+    }
+}
+class MyArrayObject3 extends ArrayObject {
+    public function offsetExists($name) {
+        echo "offsetExists($name)\n";
+        return parent::offsetExists($name);
+    }
+}
+
+$arr = [1 => [1 => 42]];
+$ao = new ArrayObject($arr);
+var_dump(isset($ao[0][1]));
+var_dump(isset($ao[1][0]));
+var_dump(isset($ao[1][1]));
+$ao = new MyArrayObject1($arr);
+var_dump(isset($ao[0][1]));
+var_dump(isset($ao[1][0]));
+var_dump(isset($ao[1][1]));
+$ao = new MyArrayObject2($arr);
+var_dump(isset($ao[0][1]));
+var_dump(isset($ao[1][0]));
+var_dump(isset($ao[1][1]));
+$ao = new MyArrayObject3($arr);
+var_dump(isset($ao[0][1]));
+var_dump(isset($ao[1][0]));
+var_dump(isset($ao[1][1]));
+
+?>
+--EXPECT--
+bool(false)
+bool(false)
+bool(true)
+offsetExists(0)
+bool(false)
+offsetExists(1)
+offsetGet(1)
+bool(false)
+offsetExists(1)
+offsetGet(1)
+bool(true)
+bool(false)
+offsetGet(1)
+bool(false)
+offsetGet(1)
+bool(true)
+offsetExists(0)
+bool(false)
+offsetExists(1)
+bool(false)
+offsetExists(1)
+bool(true)