summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Joye <pajoye@php.net>2010-07-13 18:53:12 +0000
committerPierre Joye <pajoye@php.net>2010-07-13 18:53:12 +0000
commite246625a57d0877fce298aae06954adc8ae615fb (patch)
tree260e33876760a2e157da794c4a1dedb83c49405d
parente92d4a936d4c722ae09d5197d6c1465bcc8d5b0d (diff)
downloadphp-git-e246625a57d0877fce298aae06954adc8ae615fb.tar.gz
- MFH: Fix a bug when var_export() causes a fatal error that could inadvertently display data due to flushing of the output buffer.
-rw-r--r--ext/standard/php_var.h2
-rw-r--r--ext/standard/tests/general_functions/var_export_error2.phpt7
-rw-r--r--ext/standard/tests/general_functions/var_export_error3.phpt9
-rw-r--r--ext/standard/var.c134
4 files changed, 96 insertions, 56 deletions
diff --git a/ext/standard/php_var.h b/ext/standard/php_var.h
index 1e19ed5f97..44988913b3 100644
--- a/ext/standard/php_var.h
+++ b/ext/standard/php_var.h
@@ -33,6 +33,8 @@ PHP_FUNCTION(memory_get_peak_usage);
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; */
diff --git a/ext/standard/tests/general_functions/var_export_error2.phpt b/ext/standard/tests/general_functions/var_export_error2.phpt
index 93d0dc1646..2b306696a6 100644
--- a/ext/standard/tests/general_functions/var_export_error2.phpt
+++ b/ext/standard/tests/general_functions/var_export_error2.phpt
@@ -14,12 +14,5 @@ var_export($obj, true);
?>
===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
diff --git a/ext/standard/tests/general_functions/var_export_error3.phpt b/ext/standard/tests/general_functions/var_export_error3.phpt
index 4ad5121682..03ed496aca 100644
--- a/ext/standard/tests/general_functions/var_export_error3.phpt
+++ b/ext/standard/tests/general_functions/var_export_error3.phpt
@@ -14,14 +14,5 @@ var_export($a, true);
?>
===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
diff --git a/ext/standard/var.c b/ext/standard/var.c
index d52c48b943..6d0dd6828d 100644
--- a/ext/standard/var.c
+++ b/ext/standard/var.c
@@ -346,54 +346,83 @@ PHP_FUNCTION(debug_zval_dump)
}
/* }}} */
+#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 @@ PHPAPI void php_var_export(zval **struc, int level TSRMLS_DC)
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 @@ 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_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);
}
/* }}} */