summaryrefslogtreecommitdiff
path: root/ext/standard/var.c
diff options
context:
space:
mode:
authorScott MacVicar <scottmac@php.net>2010-07-09 21:19:27 +0000
committerScott MacVicar <scottmac@php.net>2010-07-09 21:19:27 +0000
commitc02f6724a815e2cf5c69880cbe8107a28d690b0d (patch)
tree620dd9e48eb0813a7d121a3adba0d3db8172e081 /ext/standard/var.c
parentf20dd1f9ae699ee5f046d4ef4576e83aac35371d (diff)
downloadphp-git-c02f6724a815e2cf5c69880cbe8107a28d690b0d.tar.gz
Doing this as a seperate commit unless we need to back it out.
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.
Diffstat (limited to 'ext/standard/var.c')
-rw-r--r--ext/standard/var.c130
1 files changed, 93 insertions, 37 deletions
diff --git a/ext/standard/var.c b/ext/standard/var.c
index 9408454c63..3479dc4b8f 100644
--- a/ext/standard/var.c
+++ b/ext/standard/var.c
@@ -334,27 +334,47 @@ 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);
+
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 +382,33 @@ static int php_array_element_export(zval **zv TSRMLS_DC, int num_args, va_list a
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 +418,109 @@ 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 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, 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])
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_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);
}
/* }}} */