]> granicus.if.org Git - php/commitdiff
Fix construction of AO with overloaded object error
authorNikita Popov <nikic@php.net>
Wed, 24 Feb 2016 21:31:17 +0000 (22:31 +0100)
committerNikita Popov <nikic@php.net>
Wed, 24 Feb 2016 21:34:50 +0000 (22:34 +0100)
a) Fix uses of zend_string in error message
b) Don't assign the overloaded object as the backing storage, that
   sort of defeats the point. Instead leave the previous value.

ext/spl/spl_array.c
ext/spl/tests/ArrayObject_overloaded_object_incompatible.phpt [new file with mode: 0644]

index 070df29852099a15b0e00ccc64f7edc7007154f9..685dd27092acb70f3613aa6458162916d9a6f6ca 100644 (file)
@@ -1094,13 +1094,13 @@ static void spl_array_set_array(zval *object, spl_array_object *intern, zval *ar
                return;
        }
 
-       zval_ptr_dtor(&intern->array);
-
        if (Z_TYPE_P(array) == IS_ARRAY) {
                //??? TODO: try to avoid array duplication
+               zval_ptr_dtor(&intern->array);
                ZVAL_DUP(&intern->array, array);
        } else {
                if (Z_OBJ_HT_P(array) == &spl_handler_ArrayObject || Z_OBJ_HT_P(array) == &spl_handler_ArrayIterator) {
+                       zval_ptr_dtor(&intern->array);
                        if (just_array) {
                                spl_array_object *other = Z_SPLARRAY_P(array);
                                ar_flags = other->ar_flags & ~SPL_ARRAY_INT_MASK;
@@ -1114,11 +1114,13 @@ static void spl_array_set_array(zval *object, spl_array_object *intern, zval *ar
                        }
                } else {
                        zend_object_get_properties_t handler = Z_OBJ_HANDLER_P(array, get_properties);
-                       if (handler != std_object_handlers.get_properties
-                               || !spl_array_get_hash_table(intern)) {
-                               ZVAL_UNDEF(&intern->array);
-                               zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "Overloaded object of type %s is not compatible with %s", Z_OBJCE_P(array)->name, intern->std.ce->name);
+                       if (handler != std_object_handlers.get_properties) {
+                               zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0,
+                                       "Overloaded object of type %s is not compatible with %s",
+                                       ZSTR_VAL(Z_OBJCE_P(array)->name), ZSTR_VAL(intern->std.ce->name));
+                               return;
                        }
+                       zval_ptr_dtor(&intern->array);
                        ZVAL_COPY(&intern->array, array);
                }
        }
diff --git a/ext/spl/tests/ArrayObject_overloaded_object_incompatible.phpt b/ext/spl/tests/ArrayObject_overloaded_object_incompatible.phpt
new file mode 100644 (file)
index 0000000..8c1121b
--- /dev/null
@@ -0,0 +1,27 @@
+--TEST--
+Objects with overloaded get_properties are incompatible with ArrayObject
+--FILE--
+<?php
+
+$ao = new ArrayObject([1, 2, 3]);
+try {
+    $ao->exchangeArray(new SplFixedArray);
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+var_dump($ao);
+
+?>
+--EXPECT--
+Overloaded object of type SplFixedArray is not compatible with ArrayObject
+object(ArrayObject)#1 (1) {
+  ["storage":"ArrayObject":private]=>
+  array(3) {
+    [0]=>
+    int(1)
+    [1]=>
+    int(2)
+    [2]=>
+    int(3)
+  }
+}