colder                                   Thu, 13 Aug 2009 22:07:05 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=287266

Log:
Fix several recursion problems when var_dump'ing self-referencing objects

Changed paths:
    U   php/php-src/branches/PHP_5_3/ext/spl/spl_array.c
    U   php/php-src/branches/PHP_5_3/ext/spl/spl_dllist.c
    U   php/php-src/branches/PHP_5_3/ext/spl/spl_heap.c
    U   php/php-src/branches/PHP_5_3/ext/spl/spl_observer.c
    A   
php/php-src/branches/PHP_5_3/ext/spl/tests/SplObjectStorage_var_dump.phpt
    A   php/php-src/branches/PHP_5_3/ext/spl/tests/array_027.phpt
    A   php/php-src/branches/PHP_5_3/ext/spl/tests/dllist_012.phpt
    A   php/php-src/branches/PHP_5_3/ext/spl/tests/heap_012.phpt
    U   php/php-src/trunk/ext/spl/spl_array.c
    U   php/php-src/trunk/ext/spl/spl_dllist.c
    U   php/php-src/trunk/ext/spl/spl_heap.c
    U   php/php-src/trunk/ext/spl/spl_observer.c
    A   php/php-src/trunk/ext/spl/tests/SplObjectStorage_var_dump.phpt
    A   php/php-src/trunk/ext/spl/tests/array_027.phpt
    A   php/php-src/trunk/ext/spl/tests/dllist_012.phpt
    A   php/php-src/trunk/ext/spl/tests/heap_012.phpt

Modified: php/php-src/branches/PHP_5_3/ext/spl/spl_array.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/spl/spl_array.c	2009-08-13 20:19:31 UTC (rev 287265)
+++ php/php-src/branches/PHP_5_3/ext/spl/spl_array.c	2009-08-13 22:07:05 UTC (rev 287266)
@@ -76,6 +76,7 @@
 	zend_class_entry       *ce_get_iterator;
 	php_serialize_data_t   *serialize_data;
 	php_unserialize_data_t *unserialize_data;
+	HashTable              *debug_info;
 } spl_array_object;

 static inline HashTable *spl_array_get_hash_table(spl_array_object* intern, int check_std_props TSRMLS_DC) { /* {{{ */
@@ -144,6 +145,11 @@
 	zval_ptr_dtor(&intern->array);
 	zval_ptr_dtor(&intern->retval);

+	if (intern->debug_info != NULL) {
+		zend_hash_destroy(intern->debug_info);
+		efree(intern->debug_info);
+	}
+
 	efree(object);
 }
 /* }}} */
@@ -172,6 +178,7 @@
 	intern->ar_flags = 0;
 	intern->serialize_data   = NULL;
 	intern->unserialize_data = NULL;
+	intern->debug_info       = NULL;
 	intern->ce_get_iterator = spl_ce_ArrayIterator;
 	if (orig) {
 		spl_array_object *other = (spl_array_object*)zend_object_store_get_object(orig TSRMLS_CC);
@@ -677,32 +684,34 @@
 static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ */
 {
 	spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(obj TSRMLS_CC);
-	HashTable *rv;
 	zval *tmp, *storage;
 	int name_len;
 	char *zname;
 	zend_class_entry *base;

+	*is_temp = 0;
+
 	if (HASH_OF(intern->array) == intern->std.properties) {
-		*is_temp = 0;
 		return intern->std.properties;
 	} else {
-		*is_temp = 1;
+		if (intern->debug_info == NULL) {
+			ALLOC_HASHTABLE(intern->debug_info);
+			ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0);
+		}

-		ALLOC_HASHTABLE(rv);
-		ZEND_INIT_SYMTABLE_EX(rv, zend_hash_num_elements(intern->std.properties) + 1, 0);
+		if (intern->debug_info->nApplyCount == 0) {
+			zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));

-		zend_hash_copy(rv, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+			storage = intern->array;
+			zval_add_ref(&storage);

-		storage = intern->array;
-		zval_add_ref(&storage);
+			base = (Z_OBJ_HT_P(obj) == &spl_handler_ArrayIterator) ? spl_ce_ArrayIterator : spl_ce_ArrayObject;
+			zname = spl_gen_private_prop_name(base, "storage", sizeof("storage")-1, &name_len TSRMLS_CC);
+			zend_symtable_update(intern->debug_info, zname, name_len+1, &storage, sizeof(zval *), NULL);
+			efree(zname);
+		}

-		base = (Z_OBJ_HT_P(obj) == &spl_handler_ArrayIterator) ? spl_ce_ArrayIterator : spl_ce_ArrayObject;
-		zname = spl_gen_private_prop_name(base, "storage", sizeof("storage")-1, &name_len TSRMLS_CC);
-		zend_symtable_update(rv, zname, name_len+1, &storage, sizeof(zval *), NULL);
-		efree(zname);
-
-		return rv;
+		return intern->debug_info;
 	}
 }
 /* }}} */

Modified: php/php-src/branches/PHP_5_3/ext/spl/spl_dllist.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/spl/spl_dllist.c	2009-08-13 20:19:31 UTC (rev 287265)
+++ php/php-src/branches/PHP_5_3/ext/spl/spl_dllist.c	2009-08-13 22:07:05 UTC (rev 287266)
@@ -94,6 +94,7 @@
 	zend_function         *fptr_offset_del;
 	zend_function         *fptr_count;
 	zend_class_entry      *ce_get_iterator;
+	HashTable             *debug_info;
 };

 /* define an overloaded iterator structure */
@@ -351,6 +352,11 @@
 	SPL_LLIST_CHECK_DELREF(intern->traverse_pointer);
 	zval_ptr_dtor(&intern->retval);

+	if (intern->debug_info != NULL) {
+		zend_hash_destroy(intern->debug_info);
+		efree(intern->debug_info);
+	}
+
 	efree(object);
 }
 /* }}} */
@@ -374,6 +380,7 @@

 	intern->flags = 0;
 	intern->traverse_position = 0;
+	intern->debug_info = NULL;

 	if (orig) {
 		spl_dllist_object *other = (spl_dllist_object*)zend_object_store_get_object(orig TSRMLS_CC);
@@ -500,44 +507,47 @@
 {
 	spl_dllist_object     *intern  = (spl_dllist_object*)zend_object_store_get_object(obj TSRMLS_CC);
 	spl_ptr_llist_element *current = intern->llist->head, *next;
-	HashTable *rv;
 	zval *tmp, zrv, *dllist_array;
 	char *pnstr;
 	int  pnlen;
-	int  i = 0;;
+	int  i = 0;

-	*is_temp = 1;
+	*is_temp = 0;

-	ALLOC_HASHTABLE(rv);
-	ZEND_INIT_SYMTABLE_EX(rv, zend_hash_num_elements(intern->std.properties) + 1, 0);
+	if (intern->debug_info == NULL) {
+		ALLOC_HASHTABLE(intern->debug_info);
+		zend_hash_init(intern->debug_info, 1, NULL, ZVAL_PTR_DTOR, 0);
+	}

-	INIT_PZVAL(&zrv);
-	Z_ARRVAL(zrv) = rv;
+	if (intern->debug_info->nApplyCount == 0) {
+		INIT_PZVAL(&zrv);
+		Z_ARRVAL(zrv) = intern->debug_info;

-	zend_hash_copy(rv, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+		zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));

-	pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC);
-	add_assoc_long_ex(&zrv, pnstr, pnlen+1, intern->flags);
-	efree(pnstr);
+		pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC);
+		add_assoc_long_ex(&zrv, pnstr, pnlen+1, intern->flags);
+		efree(pnstr);

-	ALLOC_INIT_ZVAL(dllist_array);
-	array_init(dllist_array);
+		ALLOC_INIT_ZVAL(dllist_array);
+		array_init(dllist_array);

-	while (current) {
-		next = current->next;
+		while (current) {
+			next = current->next;

-		add_index_zval(dllist_array, i, (zval *)current->data);
-		Z_ADDREF_P(current->data);
-		i++;
+			add_index_zval(dllist_array, i, (zval *)current->data);
+			Z_ADDREF_P(current->data);
+			i++;

-		current = next;
+			current = next;
+		}
+
+		pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "dllist", sizeof("dllist")-1, &pnlen TSRMLS_CC);
+		add_assoc_zval_ex(&zrv, pnstr, pnlen+1, dllist_array);
+		efree(pnstr);
 	}

-	pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "dllist", sizeof("dllist")-1, &pnlen TSRMLS_CC);
-	add_assoc_zval_ex(&zrv, pnstr, pnlen+1, dllist_array);
-	efree(pnstr);
-
-	return rv;
+	return intern->debug_info;
 }
 /* }}}} */


Modified: php/php-src/branches/PHP_5_3/ext/spl/spl_heap.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/spl/spl_heap.c	2009-08-13 20:19:31 UTC (rev 287265)
+++ php/php-src/branches/PHP_5_3/ext/spl/spl_heap.c	2009-08-13 22:07:05 UTC (rev 287266)
@@ -76,6 +76,7 @@
 	zend_class_entry   *ce_get_iterator;
 	zend_function      *fptr_cmp;
 	zend_function      *fptr_count;
+	HashTable          *debug_info;
 };

 /* define an overloaded iterator structure */
@@ -370,6 +371,12 @@
 	spl_ptr_heap_destroy(intern->heap TSRMLS_CC);

 	zval_ptr_dtor(&intern->retval);
+
+	if (intern->debug_info != NULL) {
+		zend_hash_destroy(intern->debug_info);
+		efree(intern->debug_info);
+	}
+
 	efree(object);
 }
 /* }}} */
@@ -389,8 +396,9 @@
 	zend_object_std_init(&intern->std, class_type TSRMLS_CC);
 	zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));

-	intern->flags    = 0;
-	intern->fptr_cmp = NULL;
+	intern->flags      = 0;
+	intern->fptr_cmp   = NULL;
+	intern->debug_info = NULL;

 	if (orig) {
 		spl_heap_object *other = (spl_heap_object*)zend_object_store_get_object(orig TSRMLS_CC);
@@ -514,43 +522,46 @@

 static HashTable* spl_heap_object_get_debug_info_helper(zend_class_entry *ce, zval *obj, int *is_temp TSRMLS_DC) { /* {{{ */
 	spl_heap_object *intern  = (spl_heap_object*)zend_object_store_get_object(obj TSRMLS_CC);
-	HashTable *rv;
 	zval *tmp, zrv, *heap_array;
 	char *pnstr;
 	int  pnlen;
 	int  i;

-	*is_temp = 1;
+	*is_temp = 0;

-	ALLOC_HASHTABLE(rv);
-	ZEND_INIT_SYMTABLE_EX(rv, zend_hash_num_elements(intern->std.properties) + 1, 0);
+	if (intern->debug_info == NULL) {
+		ALLOC_HASHTABLE(intern->debug_info);
+		ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0);
+	}

-	INIT_PZVAL(&zrv);
-	Z_ARRVAL(zrv) = rv;
+	if (intern->debug_info->nApplyCount == 0) {
+		INIT_PZVAL(&zrv);
+		Z_ARRVAL(zrv) = intern->debug_info;

-	zend_hash_copy(rv, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+		zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));

-	pnstr = spl_gen_private_prop_name(ce, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC);
-	add_assoc_long_ex(&zrv, pnstr, pnlen+1, intern->flags);
-	efree(pnstr);
+		pnstr = spl_gen_private_prop_name(ce, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC);
+		add_assoc_long_ex(&zrv, pnstr, pnlen+1, intern->flags);
+		efree(pnstr);

-	pnstr = spl_gen_private_prop_name(ce, "isCorrupted", sizeof("isCorrupted")-1, &pnlen TSRMLS_CC);
-	add_assoc_bool_ex(&zrv, pnstr, pnlen+1, intern->heap->flags&SPL_HEAP_CORRUPTED);
-	efree(pnstr);
+		pnstr = spl_gen_private_prop_name(ce, "isCorrupted", sizeof("isCorrupted")-1, &pnlen TSRMLS_CC);
+		add_assoc_bool_ex(&zrv, pnstr, pnlen+1, intern->heap->flags&SPL_HEAP_CORRUPTED);
+		efree(pnstr);

-	ALLOC_INIT_ZVAL(heap_array);
-	array_init(heap_array);
+		ALLOC_INIT_ZVAL(heap_array);
+		array_init(heap_array);

-	for (i = 0; i < intern->heap->count; ++i) {
-		add_index_zval(heap_array, i, (zval *)intern->heap->elements[i]);
-		Z_ADDREF_P(intern->heap->elements[i]);
+		for (i = 0; i < intern->heap->count; ++i) {
+			add_index_zval(heap_array, i, (zval *)intern->heap->elements[i]);
+			Z_ADDREF_P(intern->heap->elements[i]);
+		}
+
+		pnstr = spl_gen_private_prop_name(ce, "heap", sizeof("heap")-1, &pnlen TSRMLS_CC);
+		add_assoc_zval_ex(&zrv, pnstr, pnlen+1, heap_array);
+		efree(pnstr);
 	}

-	pnstr = spl_gen_private_prop_name(ce, "heap", sizeof("heap")-1, &pnlen TSRMLS_CC);
-	add_assoc_zval_ex(&zrv, pnstr, pnlen+1, heap_array);
-	efree(pnstr);
-
-	return rv;
+	return intern->debug_info;
 }
 /* }}} */


Modified: php/php-src/branches/PHP_5_3/ext/spl/spl_observer.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/spl/spl_observer.c	2009-08-13 20:19:31 UTC (rev 287265)
+++ php/php-src/branches/PHP_5_3/ext/spl/spl_observer.c	2009-08-13 22:07:05 UTC (rev 287266)
@@ -84,6 +84,7 @@
 	long              index;
 	HashPosition      pos;
 	long              flags;
+	HashTable        *debug_info;
 } spl_SplObjectStorage; /* }}} */

 /* {{{ storage is an assoc aray of [zend_object_value]=>[zval *obj, zval *inf] */
@@ -99,6 +100,11 @@
 	zend_object_std_dtor(&intern->std TSRMLS_CC);

 	zend_hash_destroy(&intern->storage);
+
+	if (intern->debug_info != NULL) {
+		zend_hash_destroy(intern->debug_info);
+		efree(intern->debug_info);
+	}

 	efree(object);
 } /* }}} */
@@ -238,42 +244,46 @@
 {
 	spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(obj TSRMLS_CC);
 	spl_SplObjectStorageElement *element;
-	HashTable *rv, *props;
+	HashTable *props;
 	HashPosition pos;
 	zval *tmp, *storage;
 	char md5str[33];
 	int name_len;
 	char *zname;

-	*is_temp = 1;
+	*is_temp = 0;

 	props = Z_OBJPROP_P(obj);
-	ALLOC_HASHTABLE(rv);
-	ZEND_INIT_SYMTABLE_EX(rv, zend_hash_num_elements(props) + 1, 0);
+	if (intern->debug_info == NULL) {
+		ALLOC_HASHTABLE(intern->debug_info);
+		ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(props) + 1, 0);
+	}

-	zend_hash_copy(rv, props, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+	if (intern->debug_info->nApplyCount == 0) {
+		zend_hash_copy(intern->debug_info, props, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));

-	MAKE_STD_ZVAL(storage);
-	array_init(storage);
+		MAKE_STD_ZVAL(storage);
+		array_init(storage);

-	zend_hash_internal_pointer_reset_ex(&intern->storage, &pos);
-	while (zend_hash_get_current_data_ex(&intern->storage, (void **)&element, &pos) == SUCCESS) {
-	        php_spl_object_hash(element->obj, md5str TSRMLS_CC);
-	        Z_ADDREF_P(element->obj);
-	        Z_ADDREF_P(element->inf);
-	        MAKE_STD_ZVAL(tmp);
-	        array_init(tmp);
-	        add_assoc_zval_ex(tmp, "obj", sizeof("obj"), element->obj);
-	        add_assoc_zval_ex(tmp, "inf", sizeof("inf"), element->inf);
-	        add_assoc_zval_ex(storage, md5str, 33, tmp);
-	        zend_hash_move_forward_ex(&intern->storage, &pos);
+		zend_hash_internal_pointer_reset_ex(&intern->storage, &pos);
+		while (zend_hash_get_current_data_ex(&intern->storage, (void **)&element, &pos) == SUCCESS) {
+				php_spl_object_hash(element->obj, md5str TSRMLS_CC);
+				Z_ADDREF_P(element->obj);
+				Z_ADDREF_P(element->inf);
+				MAKE_STD_ZVAL(tmp);
+				array_init(tmp);
+				add_assoc_zval_ex(tmp, "obj", sizeof("obj"), element->obj);
+				add_assoc_zval_ex(tmp, "inf", sizeof("inf"), element->inf);
+				add_assoc_zval_ex(storage, md5str, 33, tmp);
+				zend_hash_move_forward_ex(&intern->storage, &pos);
+		}
+
+		zname = spl_gen_private_prop_name(spl_ce_SplObjectStorage, "storage", sizeof("storage")-1, &name_len TSRMLS_CC);
+		zend_symtable_update(intern->debug_info, zname, name_len+1, &storage, sizeof(zval *), NULL);
+		efree(zname);
 	}

-	zname = spl_gen_private_prop_name(spl_ce_SplObjectStorage, "storage", sizeof("storage")-1, &name_len TSRMLS_CC);
-	zend_symtable_update(rv, zname, name_len+1, &storage, sizeof(zval *), NULL);
-	efree(zname);
-
-	return rv;
+	return intern->debug_info;
 }
 /* }}} */


Added: php/php-src/branches/PHP_5_3/ext/spl/tests/SplObjectStorage_var_dump.phpt
===================================================================
--- php/php-src/branches/PHP_5_3/ext/spl/tests/SplObjectStorage_var_dump.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_3/ext/spl/tests/SplObjectStorage_var_dump.phpt	2009-08-13 22:07:05 UTC (rev 287266)
@@ -0,0 +1,35 @@
+--TEST--
+SPL: SplObjectStorage: recursive var_dump
+--FILE--
+<?php
+$o = new SplObjectStorage();
+
+$o[new StdClass] = $o;
+
+var_dump($o);
+--EXPECTF--
+object(SplObjectStorage)#1 (1) {
+  ["storage":"SplObjectStorage":private]=>
+  array(1) {
+    ["%s"]=>
+    array(2) {
+      ["obj"]=>
+      object(stdClass)#2 (0) {
+      }
+      ["inf"]=>
+      object(SplObjectStorage)#1 (1) {
+        ["storage":"SplObjectStorage":private]=>
+        array(1) {
+          ["%s"]=>
+          array(2) {
+            ["obj"]=>
+            object(stdClass)#2 (0) {
+            }
+            ["inf"]=>
+            *RECURSION*
+          }
+        }
+      }
+    }
+  }
+}

Added: php/php-src/branches/PHP_5_3/ext/spl/tests/array_027.phpt
===================================================================
--- php/php-src/branches/PHP_5_3/ext/spl/tests/array_027.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_3/ext/spl/tests/array_027.phpt	2009-08-13 22:07:05 UTC (rev 287266)
@@ -0,0 +1,24 @@
+--TEST--
+SPL: ArrayObject revursive var_dump
+--FILE--
+<?php
+class AO extends ArrayObject {
+}
+$o = new AO();
+$o['plop'] = $o;
+
+var_dump($o);
+--EXPECTF--
+object(AO)#1 (1) {
+  ["storage":"ArrayObject":private]=>
+  array(1) {
+    ["plop"]=>
+    object(AO)#1 (1) {
+      ["storage":"ArrayObject":private]=>
+      array(1) {
+        ["plop"]=>
+        *RECURSION*
+      }
+    }
+  }
+}

Added: php/php-src/branches/PHP_5_3/ext/spl/tests/dllist_012.phpt
===================================================================
--- php/php-src/branches/PHP_5_3/ext/spl/tests/dllist_012.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_3/ext/spl/tests/dllist_012.phpt	2009-08-13 22:07:05 UTC (rev 287266)
@@ -0,0 +1,29 @@
+--TEST--
+SPL: DoublyLinkedList: recursive var_dump
+--FILE--
+<?php
+$a = new SplDoublyLinkedList;
+$a[] = $a;
+
+var_dump($a);
+?>
+===DONE===
+--EXPECT--
+object(SplDoublyLinkedList)#1 (2) {
+  ["flags":"SplDoublyLinkedList":private]=>
+  int(0)
+  ["dllist":"SplDoublyLinkedList":private]=>
+  array(1) {
+    [0]=>
+    object(SplDoublyLinkedList)#1 (2) {
+      ["flags":"SplDoublyLinkedList":private]=>
+      int(0)
+      ["dllist":"SplDoublyLinkedList":private]=>
+      array(1) {
+        [0]=>
+        *RECURSION*
+      }
+    }
+  }
+}
+===DONE===

Added: php/php-src/branches/PHP_5_3/ext/spl/tests/heap_012.phpt
===================================================================
--- php/php-src/branches/PHP_5_3/ext/spl/tests/heap_012.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_3/ext/spl/tests/heap_012.phpt	2009-08-13 22:07:05 UTC (rev 287266)
@@ -0,0 +1,32 @@
+--TEST--
+SPL: SplHeap recursive var_dump
+--FILE--
+<?php
+$a = new SplMaxHeap;
+$a->insert($a);
+var_dump($a)
+?>
+===DONE===
+--EXPECT--
+object(SplMaxHeap)#1 (3) {
+  ["flags":"SplHeap":private]=>
+  int(0)
+  ["isCorrupted":"SplHeap":private]=>
+  bool(false)
+  ["heap":"SplHeap":private]=>
+  array(1) {
+    [0]=>
+    object(SplMaxHeap)#1 (3) {
+      ["flags":"SplHeap":private]=>
+      int(0)
+      ["isCorrupted":"SplHeap":private]=>
+      bool(false)
+      ["heap":"SplHeap":private]=>
+      array(1) {
+        [0]=>
+        *RECURSION*
+      }
+    }
+  }
+}
+===DONE===

Modified: php/php-src/trunk/ext/spl/spl_array.c
===================================================================
--- php/php-src/trunk/ext/spl/spl_array.c	2009-08-13 20:19:31 UTC (rev 287265)
+++ php/php-src/trunk/ext/spl/spl_array.c	2009-08-13 22:07:05 UTC (rev 287266)
@@ -77,6 +77,7 @@
 	zend_class_entry       *ce_get_iterator;
 	php_serialize_data_t   *serialize_data;
 	php_unserialize_data_t *unserialize_data;
+	HashTable              *debug_info;
 } spl_array_object;

 static inline HashTable *spl_array_get_hash_table(spl_array_object* intern, int check_std_props TSRMLS_DC) { /* {{{ */
@@ -145,6 +146,11 @@
 	zval_ptr_dtor(&intern->array);
 	zval_ptr_dtor(&intern->retval);

+	if (intern->debug_info != NULL) {
+		zend_hash_destroy(intern->debug_info);
+		efree(intern->debug_info);
+	}
+
 	efree(object);
 }
 /* }}} */
@@ -173,6 +179,7 @@
 	intern->ar_flags = 0;
 	intern->serialize_data   = NULL;
 	intern->unserialize_data = NULL;
+	intern->debug_info       = NULL;
 	intern->ce_get_iterator = spl_ce_ArrayIterator;
 	if (orig) {
 		spl_array_object *other = (spl_array_object*)zend_object_store_get_object(orig TSRMLS_CC);
@@ -681,32 +688,33 @@
 static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ */
 {
 	spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(obj TSRMLS_CC);
-	HashTable *rv;
 	zval *tmp, *storage;
 	int name_len;
 	zstr zname;
 	zend_class_entry *base;

+	*is_temp = 0;
 	if (HASH_OF(intern->array) == intern->std.properties) {
-		*is_temp = 0;
 		return intern->std.properties;
 	} else {
-		*is_temp = 1;
+		if (intern->debug_info == NULL) {
+			ALLOC_HASHTABLE(intern->debug_info);
+			ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0);
+		}

-		ALLOC_HASHTABLE(rv);
-		ZEND_INIT_SYMTABLE_EX(rv, zend_hash_num_elements(intern->std.properties) + 1, 0);
+		if (intern->debug_info->nApplyCount == 0) {
+			zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+
+			storage = intern->array;
+			zval_add_ref(&storage);
+
+			base = (Z_OBJ_HT_P(obj) == &spl_handler_ArrayIterator) ? spl_ce_ArrayIterator : spl_ce_ArrayObject;
+			zname = spl_gen_private_prop_name(base, "storage", sizeof("storage")-1, &name_len TSRMLS_CC);
+			zend_u_symtable_update(intern->debug_info, IS_UNICODE, zname, name_len+1, &storage, sizeof(zval *), NULL);
+			efree(zname.v);
+		}

-		zend_hash_copy(rv, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
-
-		storage = intern->array;
-		zval_add_ref(&storage);
-
-		base = (Z_OBJ_HT_P(obj) == &spl_handler_ArrayIterator) ? spl_ce_ArrayIterator : spl_ce_ArrayObject;
-		zname = spl_gen_private_prop_name(base, "storage", sizeof("storage")-1, &name_len TSRMLS_CC);
-		zend_u_symtable_update(rv, IS_UNICODE, zname, name_len+1, &storage, sizeof(zval *), NULL);
-		efree(zname.v);
-
-		return rv;
+		return intern->debug_info;
 	}
 }
 /* }}} */

Modified: php/php-src/trunk/ext/spl/spl_dllist.c
===================================================================
--- php/php-src/trunk/ext/spl/spl_dllist.c	2009-08-13 20:19:31 UTC (rev 287265)
+++ php/php-src/trunk/ext/spl/spl_dllist.c	2009-08-13 22:07:05 UTC (rev 287266)
@@ -94,6 +94,7 @@
 	zend_function         *fptr_offset_del;
 	zend_function         *fptr_count;
 	zend_class_entry      *ce_get_iterator;
+	HashTable             *debug_info;
 };

 /* define an overloaded iterator structure */
@@ -353,6 +354,11 @@
 	SPL_LLIST_CHECK_DELREF(intern->traverse_pointer);
 	zval_ptr_dtor(&intern->retval);

+	if (intern->debug_info != NULL) {
+		zend_hash_destroy(intern->debug_info);
+		efree(intern->debug_info);
+	}
+
 	efree(object);
 }
 /* }}} */
@@ -374,6 +380,7 @@

 	intern->flags = 0;
 	intern->traverse_position = 0;
+	intern->debug_info = NULL;

 	if (orig) {
 		spl_dllist_object *other = (spl_dllist_object*)zend_object_store_get_object(orig TSRMLS_CC);
@@ -498,44 +505,47 @@
 {
 	spl_dllist_object     *intern  = (spl_dllist_object*)zend_object_store_get_object(obj TSRMLS_CC);
 	spl_ptr_llist_element *current = intern->llist->head, *next;
-	HashTable *rv;
 	zval *tmp, zrv, *dllist_array;
 	zstr pnstr;
 	int  pnlen;
 	int  i = 0;;

-	*is_temp = 1;
+	*is_temp = 0;

-	ALLOC_HASHTABLE(rv);
-	ZEND_INIT_SYMTABLE_EX(rv, zend_hash_num_elements(intern->std.properties) + 1, 0);
+	if (intern->debug_info == NULL) {
+		ALLOC_HASHTABLE(intern->debug_info);
+		ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0);
+	}

-	INIT_PZVAL(&zrv);
-	Z_ARRVAL(zrv) = rv;
+	if (intern->debug_info->nApplyCount == 0) {
+		INIT_PZVAL(&zrv);
+		Z_ARRVAL(zrv) = intern->debug_info;

-	zend_hash_copy(rv, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+		zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));

-	pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC);
-	add_u_assoc_long_ex(&zrv, IS_UNICODE, pnstr, pnlen+1, intern->flags);
-	efree(pnstr.v);
+		pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC);
+		add_u_assoc_long_ex(&zrv, IS_UNICODE, pnstr, pnlen+1, intern->flags);
+		efree(pnstr.v);

-	ALLOC_INIT_ZVAL(dllist_array);
-	array_init(dllist_array);
+		ALLOC_INIT_ZVAL(dllist_array);
+		array_init(dllist_array);

-	while (current) {
-		next = current->next;
+		while (current) {
+			next = current->next;

-		add_index_zval(dllist_array, i, (zval *)current->data);
-		Z_ADDREF_P(current->data);
-		i++;
+			add_index_zval(dllist_array, i, (zval *)current->data);
+			Z_ADDREF_P(current->data);
+			i++;

-		current = next;
+			current = next;
+		}
+
+		pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "dllist", sizeof("dllist")-1, &pnlen TSRMLS_CC);
+		add_u_assoc_zval_ex(&zrv, IS_UNICODE, pnstr, pnlen+1, dllist_array);
+		efree(pnstr.v);
 	}

-	pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "dllist", sizeof("dllist")-1, &pnlen TSRMLS_CC);
-	add_u_assoc_zval_ex(&zrv, IS_UNICODE, pnstr, pnlen+1, dllist_array);
-	efree(pnstr.v);
-
-	return rv;
+	return intern->debug_info;
 }
 /* }}}} */


Modified: php/php-src/trunk/ext/spl/spl_heap.c
===================================================================
--- php/php-src/trunk/ext/spl/spl_heap.c	2009-08-13 20:19:31 UTC (rev 287265)
+++ php/php-src/trunk/ext/spl/spl_heap.c	2009-08-13 22:07:05 UTC (rev 287266)
@@ -76,6 +76,7 @@
 	zend_class_entry   *ce_get_iterator;
 	zend_function      *fptr_cmp;
 	zend_function      *fptr_count;
+	HashTable          *debug_info;
 };

 /* define an overloaded iterator structure */
@@ -370,6 +371,12 @@
 	spl_ptr_heap_destroy(intern->heap TSRMLS_CC);

 	zval_ptr_dtor(&intern->retval);
+
+	if(intern->debug_info != NULL) {
+		zend_hash_destroy(intern->debug_info);
+		efree(intern->debug_info);
+	}
+
 	efree(object);
 }
 /* }}} */
@@ -389,8 +396,9 @@
 	zend_object_std_init(&intern->std, class_type TSRMLS_CC);
 	zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));

-	intern->flags    = 0;
-	intern->fptr_cmp = NULL;
+	intern->flags      = 0;
+	intern->fptr_cmp   = NULL;
+	intern->debug_info = NULL;

 	if (orig) {
 		spl_heap_object *other = (spl_heap_object*)zend_object_store_get_object(orig TSRMLS_CC);
@@ -514,43 +522,46 @@

 static HashTable* spl_heap_object_get_debug_info_helper(zend_class_entry *ce, zval *obj, int *is_temp TSRMLS_DC) { /* {{{ */
 	spl_heap_object *intern  = (spl_heap_object*)zend_object_store_get_object(obj TSRMLS_CC);
-	HashTable *rv;
 	zval *tmp, zrv, *heap_array;
 	zstr pnstr;
 	int  pnlen;
 	int  i;

-	*is_temp = 1;
+	*is_temp = 0;

-	ALLOC_HASHTABLE(rv);
-	ZEND_INIT_SYMTABLE_EX(rv, zend_hash_num_elements(intern->std.properties) + 1, 0);
+	if (intern->debug_info == NULL) {
+		ALLOC_HASHTABLE(intern->debug_info);
+		ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0);
+	}

-	INIT_PZVAL(&zrv);
-	Z_ARRVAL(zrv) = rv;
+	if (intern->debug_info->nApplyCount == 0) {
+		INIT_PZVAL(&zrv);
+		Z_ARRVAL(zrv) = intern->debug_info;

-	zend_hash_copy(rv, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+		zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));

-	pnstr = spl_gen_private_prop_name(ce, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC);
-	add_u_assoc_long_ex(&zrv, IS_UNICODE, pnstr, pnlen+1, intern->flags);
-	efree(pnstr.v);
+		pnstr = spl_gen_private_prop_name(ce, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC);
+		add_u_assoc_long_ex(&zrv, IS_UNICODE, pnstr, pnlen+1, intern->flags);
+		efree(pnstr.v);

-	pnstr = spl_gen_private_prop_name(ce, "isCorrupted", sizeof("isCorrupted")-1, &pnlen TSRMLS_CC);
-	add_u_assoc_bool_ex(&zrv, IS_UNICODE, pnstr, pnlen+1, intern->heap->flags&SPL_HEAP_CORRUPTED);
-	efree(pnstr.v);
+		pnstr = spl_gen_private_prop_name(ce, "isCorrupted", sizeof("isCorrupted")-1, &pnlen TSRMLS_CC);
+		add_u_assoc_bool_ex(&zrv, IS_UNICODE, pnstr, pnlen+1, intern->heap->flags&SPL_HEAP_CORRUPTED);
+		efree(pnstr.v);

-	ALLOC_INIT_ZVAL(heap_array);
-	array_init(heap_array);
+		ALLOC_INIT_ZVAL(heap_array);
+		array_init(heap_array);

-	for (i = 0; i < intern->heap->count; ++i) {
-		add_index_zval(heap_array, i, (zval *)intern->heap->elements[i]);
-		Z_ADDREF_P(intern->heap->elements[i]);
+		for (i = 0; i < intern->heap->count; ++i) {
+			add_index_zval(heap_array, i, (zval *)intern->heap->elements[i]);
+			Z_ADDREF_P(intern->heap->elements[i]);
+		}
+
+		pnstr = spl_gen_private_prop_name(ce, "heap", sizeof("heap")-1, &pnlen TSRMLS_CC);
+		add_u_assoc_zval_ex(&zrv, IS_UNICODE, pnstr, pnlen+1, heap_array);
+		efree(pnstr.v);
 	}

-	pnstr = spl_gen_private_prop_name(ce, "heap", sizeof("heap")-1, &pnlen TSRMLS_CC);
-	add_u_assoc_zval_ex(&zrv, IS_UNICODE, pnstr, pnlen+1, heap_array);
-	efree(pnstr.v);
-
-	return rv;
+	return intern->debug_info;
 }
 /* }}} */


Modified: php/php-src/trunk/ext/spl/spl_observer.c
===================================================================
--- php/php-src/trunk/ext/spl/spl_observer.c	2009-08-13 20:19:31 UTC (rev 287265)
+++ php/php-src/trunk/ext/spl/spl_observer.c	2009-08-13 22:07:05 UTC (rev 287266)
@@ -84,6 +84,7 @@
 	long              index;
 	HashPosition      pos;
 	long              flags;
+	HashTable        *debug_info;
 } spl_SplObjectStorage; /* }}} */

 /* {{{ storage is an assoc aray of [zend_object_value]=>[zval *obj, zval *inf] */
@@ -100,6 +101,13 @@

 	zend_hash_destroy(&intern->storage);

+	if (intern->debug_info != NULL) {
+		zend_hash_destroy(intern->debug_info);
+		efree(intern->debug_info);
+
+	}
+
+
 	efree(object);
 } /* }}} */

@@ -239,42 +247,46 @@
 {
 	spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(obj TSRMLS_CC);
 	spl_SplObjectStorageElement *element;
-	HashTable *rv, *props;
+	HashTable *props;
 	HashPosition pos;
 	zval *tmp, *storage;
 	char md5str[33];
 	int name_len;
 	zstr zname;

-	*is_temp = 1;
+	*is_temp = 0;

 	props = Z_OBJPROP_P(obj);
-	ALLOC_HASHTABLE(rv);
-	ZEND_INIT_SYMTABLE_EX(rv, zend_hash_num_elements(props) + 1, 0);
+	if (intern->debug_info == NULL) {
+		ALLOC_HASHTABLE(intern->debug_info);
+		ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(props) + 1, 0);
+	}

-	zend_hash_copy(rv, props, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
+	if (intern->debug_info->nApplyCount == 0) {
+		zend_hash_copy(intern->debug_info, props, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));

-	MAKE_STD_ZVAL(storage);
-	array_init(storage);
+		MAKE_STD_ZVAL(storage);
+		array_init(storage);

-	zend_hash_internal_pointer_reset_ex(&intern->storage, &pos);
-	while (zend_hash_get_current_data_ex(&intern->storage, (void **)&element, &pos) == SUCCESS) {
-	        php_spl_object_hash(element->obj, md5str TSRMLS_CC);
-	        Z_ADDREF_P(element->obj);
-	        Z_ADDREF_P(element->inf);
-	        MAKE_STD_ZVAL(tmp);
-	        array_init(tmp);
-	        add_assoc_zval_ex(tmp, "obj", sizeof("obj"), element->obj);
-	        add_assoc_zval_ex(tmp, "inf", sizeof("inf"), element->inf);
-	        add_assoc_zval_ex(storage, md5str, 33, tmp);
-	        zend_hash_move_forward_ex(&intern->storage, &pos);
+		zend_hash_internal_pointer_reset_ex(&intern->storage, &pos);
+		while (zend_hash_get_current_data_ex(&intern->storage, (void **)&element, &pos) == SUCCESS) {
+				php_spl_object_hash(element->obj, md5str TSRMLS_CC);
+				Z_ADDREF_P(element->obj);
+				Z_ADDREF_P(element->inf);
+				MAKE_STD_ZVAL(tmp);
+				array_init(tmp);
+				add_assoc_zval_ex(tmp, "obj", sizeof("obj"), element->obj);
+				add_assoc_zval_ex(tmp, "inf", sizeof("inf"), element->inf);
+				add_assoc_zval_ex(storage, md5str, 33, tmp);
+				zend_hash_move_forward_ex(&intern->storage, &pos);
+		}
+
+		zname = spl_gen_private_prop_name(spl_ce_SplObjectStorage, "storage", sizeof("storage")-1, &name_len TSRMLS_CC);
+		zend_u_symtable_update(intern->debug_info, IS_UNICODE, zname, name_len+1, &storage, sizeof(zval *), NULL);
+		efree(zname.v);
 	}

-	zname = spl_gen_private_prop_name(spl_ce_SplObjectStorage, "storage", sizeof("storage")-1, &name_len TSRMLS_CC);
-	zend_u_symtable_update(rv, IS_UNICODE, zname, name_len+1, &storage, sizeof(zval *), NULL);
-	efree(zname.v);
-
-	return rv;
+	return intern->debug_info;
 }
 /* }}} */


Added: php/php-src/trunk/ext/spl/tests/SplObjectStorage_var_dump.phpt
===================================================================
--- php/php-src/trunk/ext/spl/tests/SplObjectStorage_var_dump.phpt	                        (rev 0)
+++ php/php-src/trunk/ext/spl/tests/SplObjectStorage_var_dump.phpt	2009-08-13 22:07:05 UTC (rev 287266)
@@ -0,0 +1,35 @@
+--TEST--
+SPL: SplObjectStorage: recursive var_dump
+--FILE--
+<?php
+$o = new SplObjectStorage();
+
+$o[new StdClass] = $o;
+
+var_dump($o);
+--EXPECTF--
+object(SplObjectStorage)#1 (1) {
+  [u"storage":u"SplObjectStorage":private]=>
+  array(1) {
+    ["%s"]=>
+    array(2) {
+      ["obj"]=>
+      object(stdClass)#2 (0) {
+      }
+      ["inf"]=>
+      object(SplObjectStorage)#1 (1) {
+        [u"storage":u"SplObjectStorage":private]=>
+        array(1) {
+          ["%s"]=>
+          array(2) {
+            ["obj"]=>
+            object(stdClass)#2 (0) {
+            }
+            ["inf"]=>
+            *RECURSION*
+          }
+        }
+      }
+    }
+  }
+}

Added: php/php-src/trunk/ext/spl/tests/array_027.phpt
===================================================================
--- php/php-src/trunk/ext/spl/tests/array_027.phpt	                        (rev 0)
+++ php/php-src/trunk/ext/spl/tests/array_027.phpt	2009-08-13 22:07:05 UTC (rev 287266)
@@ -0,0 +1,24 @@
+--TEST--
+SPL: ArrayObject revursive var_dump
+--FILE--
+<?php
+class AO extends ArrayObject {
+}
+$o = new AO();
+$o['plop'] = $o;
+
+var_dump($o);
+--EXPECTF--
+object(AO)#1 (1) {
+  [u"storage":u"ArrayObject":private]=>
+  array(1) {
+    [u"plop"]=>
+    object(AO)#1 (1) {
+      [u"storage":u"ArrayObject":private]=>
+      array(1) {
+        [u"plop"]=>
+        *RECURSION*
+      }
+    }
+  }
+}

Added: php/php-src/trunk/ext/spl/tests/dllist_012.phpt
===================================================================
--- php/php-src/trunk/ext/spl/tests/dllist_012.phpt	                        (rev 0)
+++ php/php-src/trunk/ext/spl/tests/dllist_012.phpt	2009-08-13 22:07:05 UTC (rev 287266)
@@ -0,0 +1,29 @@
+--TEST--
+SPL: DoublyLinkedList: recursive var_dump
+--FILE--
+<?php
+$a = new SplDoublyLinkedList;
+$a[] = $a;
+
+var_dump($a);
+?>
+===DONE===
+--EXPECT--
+object(SplDoublyLinkedList)#1 (2) {
+  [u"flags":u"SplDoublyLinkedList":private]=>
+  int(0)
+  [u"dllist":u"SplDoublyLinkedList":private]=>
+  array(1) {
+    [0]=>
+    object(SplDoublyLinkedList)#1 (2) {
+      [u"flags":u"SplDoublyLinkedList":private]=>
+      int(0)
+      [u"dllist":u"SplDoublyLinkedList":private]=>
+      array(1) {
+        [0]=>
+        *RECURSION*
+      }
+    }
+  }
+}
+===DONE===

Added: php/php-src/trunk/ext/spl/tests/heap_012.phpt
===================================================================
--- php/php-src/trunk/ext/spl/tests/heap_012.phpt	                        (rev 0)
+++ php/php-src/trunk/ext/spl/tests/heap_012.phpt	2009-08-13 22:07:05 UTC (rev 287266)
@@ -0,0 +1,32 @@
+--TEST--
+SPL: SplHeap recursive var_dump
+--FILE--
+<?php
+$a = new SplMaxHeap;
+$a->insert($a);
+var_dump($a)
+?>
+===DONE===
+--EXPECT--
+object(SplMaxHeap)#1 (3) {
+  [u"flags":u"SplHeap":private]=>
+  int(0)
+  [u"isCorrupted":u"SplHeap":private]=>
+  bool(false)
+  [u"heap":u"SplHeap":private]=>
+  array(1) {
+    [0]=>
+    object(SplMaxHeap)#1 (3) {
+      [u"flags":u"SplHeap":private]=>
+      int(0)
+      [u"isCorrupted":u"SplHeap":private]=>
+      bool(false)
+      [u"heap":u"SplHeap":private]=>
+      array(1) {
+        [0]=>
+        *RECURSION*
+      }
+    }
+  }
+}
+===DONE===
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to