scottmac                                 Fri, 09 Jul 2010 21:11:37 +0000

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

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

Examples include, memory limit, execution time and recursion.

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

Modified: php/php-src/trunk/ext/standard/php_var.h
===================================================================
--- php/php-src/trunk/ext/standard/php_var.h	2010-07-09 19:54:58 UTC (rev 301142)
+++ php/php-src/trunk/ext/standard/php_var.h	2010-07-09 21:11:37 UTC (rev 301143)
@@ -34,6 +34,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);

 typedef HashTable* php_serialize_data_t;

Modified: php/php-src/trunk/ext/standard/tests/general_functions/var_export_error2.phpt
===================================================================
--- php/php-src/trunk/ext/standard/tests/general_functions/var_export_error2.phpt	2010-07-09 19:54:58 UTC (rev 301142)
+++ php/php-src/trunk/ext/standard/tests/general_functions/var_export_error2.phpt	2010-07-09 21:11:37 UTC (rev 301143)
@@ -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/trunk/ext/standard/tests/general_functions/var_export_error3.phpt
===================================================================
--- php/php-src/trunk/ext/standard/tests/general_functions/var_export_error3.phpt	2010-07-09 19:54:58 UTC (rev 301142)
+++ php/php-src/trunk/ext/standard/tests/general_functions/var_export_error3.phpt	2010-07-09 21:11:37 UTC (rev 301143)
@@ -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/trunk/ext/standard/var.c
===================================================================
--- php/php-src/trunk/ext/standard/var.c	2010-07-09 19:54:58 UTC (rev 301142)
+++ php/php-src/trunk/ext/standard/var.c	2010-07-09 21:11:37 UTC (rev 301143)
@@ -334,27 +334,48 @@
 }
 /* }}} */

+#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);
+
 static int php_array_element_export(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
 {
 	int level;
+	smart_str *buf;

 	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);
+		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;
 }
 /* }}} */
@@ -362,24 +383,31 @@
 static int php_object_element_export(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
 {
 	int level;
+	smart_str *buf;
 	char *prop_name, *class_name;

 	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;
@@ -389,82 +417,111 @@

 	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 TSRMLS_CC, (apply_func_args_t) php_array_element_export, 1, level, 0);
+		smart_str_appendl(buf, "array (\n", 8);
+		zend_hash_apply_with_arguments(myht TSRMLS_CC, (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 TSRMLS_CC, (apply_func_args_t) php_object_element_export, 1, level);
+			zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) php_object_element_export, 1, 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])
    Outputs or returns a string representation of a variable */
 PHP_FUNCTION(var_export)
 {
 	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_output_start_default(TSRMLS_C);
-	}
+	php_var_export_ex(&var, 1, &buf TSRMLS_CC);
+	smart_str_0 (&buf);

-	php_var_export(&var, 1 TSRMLS_CC);
-
 	if (return_output) {
-		php_output_get_contents(return_value TSRMLS_CC);
-		php_output_discard(TSRMLS_C);
+		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