pajoye                                   Tue, 13 Jul 2010 18:53:12 +0000

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

Log:
- MFH: Fix a bug when var_export() causes a fatal error that could 
inadvertently display data due to flushing of the output buffer.

Changed paths:
    U   php/php-src/branches/PHP_5_2/ext/standard/php_var.h
    U   
php/php-src/branches/PHP_5_2/ext/standard/tests/general_functions/var_export_error2.phpt
    U   
php/php-src/branches/PHP_5_2/ext/standard/tests/general_functions/var_export_error3.phpt
    U   php/php-src/branches/PHP_5_2/ext/standard/var.c

Modified: php/php-src/branches/PHP_5_2/ext/standard/php_var.h
===================================================================
--- php/php-src/branches/PHP_5_2/ext/standard/php_var.h	2010-07-13 17:24:44 UTC (rev 301244)
+++ php/php-src/branches/PHP_5_2/ext/standard/php_var.h	2010-07-13 18:53:12 UTC (rev 301245)
@@ -33,6 +33,8 @@

 PHPAPI void php_var_dump(zval **struc, int level TSRMLS_DC);
 PHPAPI void php_var_export(zval **struc, int level TSRMLS_DC);
+PHPAPI void php_var_export_ex(zval **struc, int level, smart_str *buf TSRMLS_DC);
+
 PHPAPI void php_debug_zval_dump(zval **struc, int level TSRMLS_DC);

 /* typdef HashTable php_serialize_data_t; */

Modified: php/php-src/branches/PHP_5_2/ext/standard/tests/general_functions/var_export_error2.phpt
===================================================================
--- php/php-src/branches/PHP_5_2/ext/standard/tests/general_functions/var_export_error2.phpt	2010-07-13 17:24:44 UTC (rev 301244)
+++ php/php-src/branches/PHP_5_2/ext/standard/tests/general_functions/var_export_error2.phpt	2010-07-13 18:53:12 UTC (rev 301245)
@@ -14,12 +14,5 @@
 ?>
 ===DONE===
 --EXPECTF--
-stdClass::__set_state(array(
-   'p' =>
-  stdClass::__set_state(array(
-     'p' =>
-    stdClass::__set_state(array(
-       'p' =>
-      stdClass::__set_state(array(

 Fatal error: Nesting level too deep - recursive dependency? in %s on line 9
\ No newline at end of file

Modified: php/php-src/branches/PHP_5_2/ext/standard/tests/general_functions/var_export_error3.phpt
===================================================================
--- php/php-src/branches/PHP_5_2/ext/standard/tests/general_functions/var_export_error3.phpt	2010-07-13 17:24:44 UTC (rev 301244)
+++ php/php-src/branches/PHP_5_2/ext/standard/tests/general_functions/var_export_error3.phpt	2010-07-13 18:53:12 UTC (rev 301245)
@@ -14,14 +14,5 @@
 ?>
 ===DONE===
 --EXPECTF--
-array (
-  0 =>
-  array (
-    0 =>
-    array (
-      0 =>
-      array (
-        0 =>
-        array (

 Fatal error: Nesting level too deep - recursive dependency? in %s on line 9
\ No newline at end of file

Modified: php/php-src/branches/PHP_5_2/ext/standard/var.c
===================================================================
--- php/php-src/branches/PHP_5_2/ext/standard/var.c	2010-07-13 17:24:44 UTC (rev 301244)
+++ php/php-src/branches/PHP_5_2/ext/standard/var.c	2010-07-13 18:53:12 UTC (rev 301245)
@@ -346,54 +346,83 @@
 }
 /* }}} */

+#define buffer_append_spaces(buf, num_spaces) \
+	do { \
+		char *tmp_spaces; \
+		int tmp_spaces_len; \
+		tmp_spaces_len = spprintf(&tmp_spaces, 0,"%*c", num_spaces, ' '); \
+		smart_str_appendl(buf, tmp_spaces, tmp_spaces_len); \
+		efree(tmp_spaces); \
+	} while(0);
 /* {{{ php_var_export */

 static int php_array_element_export(zval **zv, int num_args, va_list args, zend_hash_key *hash_key)
 {
 	int level;
+	smart_str *buf;
+
 	TSRMLS_FETCH();

 	level = va_arg(args, int);
+	buf = va_arg(args, smart_str *);

-	if (hash_key->nKeyLength==0) { /* numeric key */
-		php_printf("%*c%ld => ", level + 1, ' ', hash_key->h);
+	if (hash_key->nKeyLength == 0) { /* numeric key */
+		buffer_append_spaces(buf, level+1);
+		smart_str_append_long(buf, hash_key->h);
+		smart_str_appendl(buf, " => ", 4);
 	} else { /* string key */
 		char *key, *tmp_str;
 		int key_len, tmp_len;
 		key = php_addcslashes(hash_key->arKey, hash_key->nKeyLength - 1, &key_len, 0, "'\\", 2 TSRMLS_CC);
 		tmp_str = php_str_to_str_ex(key, key_len, "\0", 1, "' . \"\\0\" . '", 12, &tmp_len, 0, NULL);
-		php_printf("%*c'", level + 1, ' ');
-		PHPWRITE(tmp_str, tmp_len);
-		php_printf("' => ");
+
+		buffer_append_spaces(buf, level + 1);
+
+		smart_str_appendc(buf, '\'');
+		smart_str_appendl(buf, tmp_str, tmp_len);
+		smart_str_appendl(buf, "' => ", 5);
+
 		efree(key);
 		efree(tmp_str);
 	}
-	php_var_export(zv, level + 2 TSRMLS_CC);
-	PUTS (",\n");
+	php_var_export_ex(zv, level + 2, buf TSRMLS_CC);
+
+	smart_str_appendc(buf, ',');
+	smart_str_appendc(buf, '\n');
+
 	return 0;
 }

 static int php_object_element_export(zval **zv, int num_args, va_list args, zend_hash_key *hash_key)
 {
 	int level;
+	smart_str *buf;
 	char *prop_name, *class_name;
 	TSRMLS_FETCH();

 	level = va_arg(args, int);
+	buf = va_arg(args, smart_str *);

-	php_printf("%*c", level + 1, ' ');
+	buffer_append_spaces(buf, level + 2);
 	if (hash_key->nKeyLength != 0) {
 		zend_unmangle_property_name(hash_key->arKey, hash_key->nKeyLength - 1, &class_name, &prop_name);
-		php_printf(" '%s' => ", prop_name);
+
+		smart_str_appendc(buf, '\'');
+		smart_str_appends(buf, prop_name);
+		smart_str_appendc(buf, '\'');
 	} else {
-		php_printf(" %ld => ", hash_key->h);
+		smart_str_append_long(buf, hash_key->h);
 	}
-	php_var_export(zv, level + 2 TSRMLS_CC);
-	PUTS (",\n");
+
+	smart_str_appendl(buf, " => ", 4);
+	php_var_export_ex(zv, level + 2, buf TSRMLS_CC);
+	smart_str_appendc(buf, ',');
+	smart_str_appendc(buf, '\n');
+
 	return 0;
 }

-PHPAPI void php_var_export(zval **struc, int level TSRMLS_DC)
+PHPAPI void php_var_export_ex(zval **struc, int level, smart_str *buf TSRMLS_DC) /* {{{ */
 {
 	HashTable *myht;
  	char *tmp_str, *tmp_str2;
@@ -403,60 +432,85 @@

 	switch (Z_TYPE_PP(struc)) {
 	case IS_BOOL:
-		php_printf("%s", Z_LVAL_PP(struc) ? "true" : "false");
+		if (Z_LVAL_PP(struc)) {
+			smart_str_appendl(buf, "true", 4);
+		} else {
+			smart_str_appendl(buf, "false", 5);
+		}
 		break;
 	case IS_NULL:
-		php_printf("NULL");
+		smart_str_appendl(buf, "NULL", 4);
 		break;
 	case IS_LONG:
-		php_printf("%ld", Z_LVAL_PP(struc));
+		smart_str_append_long(buf, Z_LVAL_PP(struc));
 		break;
 	case IS_DOUBLE:
-		php_printf("%.*H", (int) EG(precision), Z_DVAL_PP(struc));
+		tmp_len = spprintf(&tmp_str, 0,"%.*H", (int) EG(precision), Z_DVAL_PP(struc));
+		smart_str_appendl(buf, tmp_str, tmp_len);
+		efree(tmp_str);
 		break;
 	case IS_STRING:
 		tmp_str = php_addcslashes(Z_STRVAL_PP(struc), Z_STRLEN_PP(struc), &tmp_len, 0, "'\\", 2 TSRMLS_CC);
 		tmp_str2 = php_str_to_str_ex(tmp_str, tmp_len, "\0", 1, "' . \"\\0\" . '", 12, &tmp_len2, 0, NULL);
-		PUTS ("'");
-		PHPWRITE(tmp_str2, tmp_len2);
-		PUTS ("'");
+
+		smart_str_appendc(buf, '\'');
+		smart_str_appendl(buf, tmp_str2, tmp_len2);
+		smart_str_appendc(buf, '\'');
+
 		efree(tmp_str2);
 		efree(tmp_str);
 		break;
 	case IS_ARRAY:
 		myht = Z_ARRVAL_PP(struc);
 		if (level > 1) {
-			php_printf("\n%*c", level - 1, ' ');
+			smart_str_appendc(buf, '\n');
+			buffer_append_spaces(buf, level - 1);
 		}
-		PUTS ("array (\n");
-		zend_hash_apply_with_arguments(myht, (apply_func_args_t) php_array_element_export, 1, level, 0);
+		smart_str_appendl(buf, "array (\n", 8);
+		zend_hash_apply_with_arguments(myht, (apply_func_args_t) php_array_element_export, 2, level, buf);
+
 		if (level > 1) {
-			php_printf("%*c", level - 1, ' ');
+			buffer_append_spaces(buf, level - 1);
 		}
-		PUTS(")");
+		smart_str_appendc(buf, ')');
+
 		break;
 	case IS_OBJECT:
 		myht = Z_OBJPROP_PP(struc);
 		if (level > 1) {
-			php_printf("\n%*c", level - 1, ' ');
+			smart_str_appendc(buf, '\n');
+			buffer_append_spaces(buf, level - 1);
 		}
 		Z_OBJ_HANDLER(**struc, get_class_name)(*struc, &class_name, &class_name_len, 0 TSRMLS_CC);
-		php_printf ("%s::__set_state(array(\n", class_name);
+
+		smart_str_appendl(buf, class_name, class_name_len);
+		smart_str_appendl(buf, "::__set_state(array(\n", 21);
+
 		efree(class_name);
 		if (myht) {
-			zend_hash_apply_with_arguments(myht, (apply_func_args_t) php_object_element_export, 1, level);
+			zend_hash_apply_with_arguments(myht, (apply_func_args_t) php_object_element_export, 2, level, buf);
 		}
 		if (level > 1) {
-			php_printf("%*c", level - 1, ' ');
+			buffer_append_spaces(buf, level - 1);
 		}
-		php_printf ("))");
+		smart_str_appendl(buf, "))", 2);
+
 		break;
 	default:
-		PUTS ("NULL");
+		smart_str_appendl(buf, "NULL", 4);
 		break;
 	}
 }

+/* FOR BC reasons, this will always perform and then print */
+PHPAPI void php_var_export(zval **struc, int level TSRMLS_DC) /* {{{ */
+{
+	smart_str buf = {0};
+	php_var_export_ex(struc, level, &buf TSRMLS_CC);
+	smart_str_0 (&buf);
+	PHPWRITE(buf.c, buf.len);
+	smart_str_free(&buf);
+}
 /* }}} */

 /* {{{ proto mixed var_export(mixed var [, bool return])
@@ -465,21 +519,21 @@
 {
 	zval *var;
 	zend_bool return_output = 0;
-
+	smart_str buf = {0};
+
 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &var, &return_output) == FAILURE) {
 		return;
 	}
-
-	if (return_output) {
-		php_start_ob_buffer (NULL, 0, 1 TSRMLS_CC);
-	}
-
-	php_var_export(&var, 1 TSRMLS_CC);

+	php_var_export_ex(&var, 1, &buf TSRMLS_CC);
+	smart_str_0 (&buf);
+
 	if (return_output) {
-		php_ob_get_buffer (return_value TSRMLS_CC);
-		php_end_ob_buffer (0, 0 TSRMLS_CC);
+		RETVAL_STRINGL(buf.c, buf.len, 1);
+	} else {
+		PHPWRITE(buf.c, buf.len);
 	}
+	smart_str_free(&buf);
 }
 /* }}} */

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to