mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
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.
This commit is contained in:
parent
5438a9d23c
commit
c7b0abe6aa
4 changed files with 96 additions and 53 deletions
|
@ -34,6 +34,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);
|
||||
|
||||
typedef HashTable* php_serialize_data_t;
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -334,27 +334,48 @@ 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 +383,31 @@ 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 +417,111 @@ 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, 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(&var, 1 TSRMLS_CC);
|
||||
php_var_export_ex(&var, 1, &buf TSRMLS_CC);
|
||||
smart_str_0 (&buf);
|
||||
|
||||
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);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue