From: Gustavo André dos Santos Lopes <cataphract@php.net>
Date: Thu, 22 Mar 2012 21:49:04 +0000 (+0000)
Subject: Improved on DOM object debug info handler. Added test.
X-Git-Tag: php-5.4.1RC1~40^2^2~2
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b61017c9b635f4ab00582e073f7c17894be88980;p=php

Improved on DOM object debug info handler. Added test.
---

diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c
index 52c778a834..e65f58c925 100644
--- a/ext/dom/php_dom.c
+++ b/ext/dom/php_dom.c
@@ -468,58 +468,76 @@ static int dom_property_exists(zval *object, zval *member, int check_empty TSRML
 
 static HashTable* dom_get_debug_info_helper(zval *object, int *is_temp TSRMLS_DC) /* {{{ */
 {
-    dom_object *obj = (dom_object *)zend_object_store_get_object(object TSRMLS_CC);
-    HashTable *debug_info, *props;
-    HashPosition pos;
-    dom_prop_handler *entry;
+	dom_object			*obj = zend_object_store_get_object(object TSRMLS_CC);
+	HashTable			*debug_info,
+						*prop_handlers = obj->prop_handler,
+						*std_props;
+	HashPosition		pos;
+	dom_prop_handler	*entry;
+	zval				*object_value,
+						*null_value;
+
+	*is_temp = 1;
+
+	ALLOC_HASHTABLE(debug_info);
+	ZEND_INIT_SYMTABLE_EX(debug_info, 32, 0);
+
+	std_props = zend_std_get_properties(object TSRMLS_CC);
+	zend_hash_copy(debug_info, std_props, (copy_ctor_func_t)zval_add_ref,
+			NULL, sizeof(zval*));
+
+	if (!prop_handlers) {
+		return debug_info;
+	}
 
-    *is_temp = 1;
+	ALLOC_INIT_ZVAL(object_value);
+	ZVAL_STRING(object_value, "(object value omitted)", 1);
 
-    ALLOC_HASHTABLE(debug_info);
-    if (! obj->prop_handler) {
-        return debug_info;
-    }
+	ALLOC_INIT_ZVAL(null_value);
+	ZVAL_NULL(null_value);
 
-    props = obj->prop_handler;
-    ZEND_INIT_SYMTABLE_EX(debug_info, zend_hash_num_elements(props) + 1, 0);
-
-    zend_hash_internal_pointer_reset_ex(props, &pos);
-    while (zend_hash_get_current_data_ex(props, (void **)&entry, &pos) == SUCCESS) {
-        zval member;
-        zval *value;
-
-        char *string_key=NULL;
-        uint string_length=0;
-        ulong num_key;
-
-        zend_hash_get_current_key_ex(props, &string_key, &string_length, &num_key, 0, &pos);
-
-        INIT_ZVAL(member);
-        ZVAL_STRINGL(&member, string_key, string_length, 0);
-        value = zend_read_property(Z_OBJCE_P(object), object, Z_STRVAL(member), Z_STRLEN(member)-1, 1 TSRMLS_CC);
-        if (value != EG(uninitialized_zval_ptr)) {
-            switch(Z_TYPE_P(value)) {
-                case IS_STRING:
-                case IS_BOOL:
-                case IS_LONG:
-                case IS_DOUBLE:
-                case IS_ARRAY:
-                    zend_hash_add(debug_info, string_key, string_length, &value, sizeof(zval *), NULL);
-                    break;
-
-                default:
-                    ZVAL_NULL(value);
-                    zend_hash_add(debug_info, string_key, string_length, &value, sizeof(zval *), NULL);
-                    break;
-            }
-        } else {
-            ZVAL_NULL(value);
-            zend_hash_add(debug_info, string_key, string_length, &value, sizeof(zval *), NULL);
-        }
-        zend_hash_move_forward_ex(props, &pos);
-    }
+	for (zend_hash_internal_pointer_reset_ex(prop_handlers, &pos);
+			zend_hash_get_current_data_ex(prop_handlers, (void **)&entry, &pos)
+					== SUCCESS;
+			zend_hash_move_forward_ex(prop_handlers, &pos)) {
+		zval	*value;
+		char	*string_key		= NULL;
+		uint	string_length	= 0;
+		ulong	num_key;
+
+		if (entry->read_func(obj, &value TSRMLS_CC) == FAILURE) {
+			continue;
+		}
+
+		if (zend_hash_get_current_key_ex(prop_handlers, &string_key,
+			&string_length, &num_key, 0, &pos) != HASH_KEY_IS_STRING) {
+			continue;
+		}
+
+		if (value == EG(uninitialized_zval_ptr)) {
+			value = null_value;
+		} else if (Z_TYPE_P(value) == IS_OBJECT) {
+			/* these are zvalues create on demand, with refcount and is_ref
+			 * status left in an uninitalized stated */
+			zval_dtor(value);
+			efree(value);
+
+			value = object_value;
+		} else {
+			/* see comment above */
+			Z_SET_REFCOUNT_P(value, 0);
+			Z_UNSET_ISREF_P(value);
+		}
+
+		zval_add_ref(&value);
+		zend_hash_add(debug_info, string_key, string_length,
+				&value, sizeof(zval *), NULL);
+	}
+
+	zval_ptr_dtor(&null_value);
+	zval_ptr_dtor(&object_value);
 
-    return debug_info;
+	return debug_info;
 }
 /* }}} */
 
diff --git a/ext/dom/tests/domobject_debug_handler.phpt b/ext/dom/tests/domobject_debug_handler.phpt
new file mode 100644
index 0000000000..3c9f133548
--- /dev/null
+++ b/ext/dom/tests/domobject_debug_handler.phpt
@@ -0,0 +1,59 @@
+--TEST--
+Objects of DOM extension: debug info object handler.
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+$xml = <<<XML
+<foo>
+	<bar>foobar</bar>
+</foo>
+XML;
+$d = new domdocument;
+$d->dynamicProperty = new stdclass;
+$d->loadXML($xml);
+print_r($d);
+--EXPECTF--
+DOMDocument Object
+(
+    [dynamicProperty] => stdClass Object
+        (
+        )
+
+    [doctype] => 
+    [implementation] => (object value omitted)
+    [documentElement] => (object value omitted)
+    [actualEncoding] => 
+    [encoding] => 
+    [xmlEncoding] => 
+    [standalone] => 1
+    [xmlStandalone] => 1
+    [version] => 1.0
+    [xmlVersion] => 1.0
+    [strictErrorChecking] => 1
+    [documentURI] => %s
+    [config] => 
+    [formatOutput] => 
+    [validateOnParse] => 
+    [resolveExternals] => 
+    [preserveWhiteSpace] => 1
+    [recover] => 
+    [substituteEntities] => 
+    [nodeName] => #document
+    [nodeValue] => 
+    [nodeType] => 9
+    [parentNode] => 
+    [childNodes] => (object value omitted)
+    [firstChild] => (object value omitted)
+    [lastChild] => (object value omitted)
+    [previousSibling] => 
+    [attributes] => 
+    [ownerDocument] => 
+    [namespaceURI] => 
+    [prefix] => 
+    [localName] => 
+    [baseURI] => %s
+    [textContent] => 
+	foobar
+
+)