mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +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_dump(zval **struc, int level TSRMLS_DC);
|
||||||
PHPAPI void php_var_export(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);
|
PHPAPI void php_debug_zval_dump(zval **struc, int level TSRMLS_DC);
|
||||||
|
|
||||||
typedef HashTable* php_serialize_data_t;
|
typedef HashTable* php_serialize_data_t;
|
||||||
|
|
|
@ -14,12 +14,5 @@ var_export($obj, true);
|
||||||
?>
|
?>
|
||||||
===DONE===
|
===DONE===
|
||||||
--EXPECTF--
|
--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
|
Fatal error: Nesting level too deep - recursive dependency? in %s on line 9
|
|
@ -14,14 +14,5 @@ var_export($a, true);
|
||||||
?>
|
?>
|
||||||
===DONE===
|
===DONE===
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
array (
|
|
||||||
0 =>
|
|
||||||
array (
|
|
||||||
0 =>
|
|
||||||
array (
|
|
||||||
0 =>
|
|
||||||
array (
|
|
||||||
0 =>
|
|
||||||
array (
|
|
||||||
|
|
||||||
Fatal error: Nesting level too deep - recursive dependency? in %s on line 9
|
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) /* {{{ */
|
static int php_array_element_export(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
|
||||||
{
|
{
|
||||||
int level;
|
int level;
|
||||||
|
smart_str *buf;
|
||||||
|
|
||||||
level = va_arg(args, int);
|
level = va_arg(args, int);
|
||||||
|
buf = va_arg(args, smart_str *);
|
||||||
|
|
||||||
if (hash_key->nKeyLength == 0) { /* numeric key */
|
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 */
|
} else { /* string key */
|
||||||
char *key, *tmp_str;
|
char *key, *tmp_str;
|
||||||
int key_len, tmp_len;
|
int key_len, tmp_len;
|
||||||
key = php_addcslashes(hash_key->arKey, hash_key->nKeyLength - 1, &key_len, 0, "'\\", 2 TSRMLS_CC);
|
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);
|
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);
|
buffer_append_spaces(buf, level + 1);
|
||||||
php_printf("' => ");
|
|
||||||
|
smart_str_appendc(buf, '\'');
|
||||||
|
smart_str_appendl(buf, tmp_str, tmp_len);
|
||||||
|
smart_str_appendl(buf, "' => ", 5);
|
||||||
|
|
||||||
efree(key);
|
efree(key);
|
||||||
efree(tmp_str);
|
efree(tmp_str);
|
||||||
}
|
}
|
||||||
php_var_export(zv, level + 2 TSRMLS_CC);
|
php_var_export_ex(zv, level + 2, buf TSRMLS_CC);
|
||||||
PUTS (",\n");
|
|
||||||
|
smart_str_appendc(buf, ',');
|
||||||
|
smart_str_appendc(buf, '\n');
|
||||||
|
|
||||||
return 0;
|
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) /* {{{ */
|
static int php_object_element_export(zval **zv TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
|
||||||
{
|
{
|
||||||
int level;
|
int level;
|
||||||
|
smart_str *buf;
|
||||||
char *prop_name, *class_name;
|
char *prop_name, *class_name;
|
||||||
|
|
||||||
level = va_arg(args, int);
|
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) {
|
if (hash_key->nKeyLength != 0) {
|
||||||
zend_unmangle_property_name(hash_key->arKey, hash_key->nKeyLength - 1, &class_name, &prop_name);
|
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 {
|
} else {
|
||||||
php_printf(" %ld => ", hash_key->h);
|
smart_str_append_long(buf, hash_key->h);
|
||||||
}
|
}
|
||||||
php_var_export(zv, level + 2 TSRMLS_CC);
|
smart_str_appendl(buf, " => ", 4);
|
||||||
PUTS (",\n");
|
php_var_export_ex(zv, level + 2, buf TSRMLS_CC);
|
||||||
|
smart_str_appendc(buf, ',');
|
||||||
|
smart_str_appendc(buf, '\n');
|
||||||
return 0;
|
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;
|
HashTable *myht;
|
||||||
char *tmp_str, *tmp_str2;
|
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)) {
|
switch (Z_TYPE_PP(struc)) {
|
||||||
case IS_BOOL:
|
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;
|
break;
|
||||||
case IS_NULL:
|
case IS_NULL:
|
||||||
php_printf("NULL");
|
smart_str_appendl(buf, "NULL", 4);
|
||||||
break;
|
break;
|
||||||
case IS_LONG:
|
case IS_LONG:
|
||||||
php_printf("%ld", Z_LVAL_PP(struc));
|
smart_str_append_long(buf, Z_LVAL_PP(struc));
|
||||||
break;
|
break;
|
||||||
case IS_DOUBLE:
|
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;
|
break;
|
||||||
case IS_STRING:
|
case IS_STRING:
|
||||||
tmp_str = php_addcslashes(Z_STRVAL_PP(struc), Z_STRLEN_PP(struc), &tmp_len, 0, "'\\", 2 TSRMLS_CC);
|
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);
|
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);
|
smart_str_appendc(buf, '\'');
|
||||||
PUTS ("'");
|
smart_str_appendl(buf, tmp_str2, tmp_len2);
|
||||||
|
smart_str_appendc(buf, '\'');
|
||||||
|
|
||||||
efree(tmp_str2);
|
efree(tmp_str2);
|
||||||
efree(tmp_str);
|
efree(tmp_str);
|
||||||
break;
|
break;
|
||||||
case IS_ARRAY:
|
case IS_ARRAY:
|
||||||
myht = Z_ARRVAL_PP(struc);
|
myht = Z_ARRVAL_PP(struc);
|
||||||
if (level > 1) {
|
if (level > 1) {
|
||||||
php_printf("\n%*c", level - 1, ' ');
|
smart_str_appendc(buf, '\n');
|
||||||
|
buffer_append_spaces(buf, level - 1);
|
||||||
}
|
}
|
||||||
PUTS ("array (\n");
|
smart_str_appendl(buf, "array (\n", 8);
|
||||||
zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) php_array_element_export, 1, level, 0);
|
zend_hash_apply_with_arguments(myht TSRMLS_CC, (apply_func_args_t) php_array_element_export, 2, level, buf);
|
||||||
|
|
||||||
if (level > 1) {
|
if (level > 1) {
|
||||||
php_printf("%*c", level - 1, ' ');
|
buffer_append_spaces(buf, level - 1);
|
||||||
}
|
}
|
||||||
PUTS(")");
|
smart_str_appendc(buf, ')');
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IS_OBJECT:
|
case IS_OBJECT:
|
||||||
myht = Z_OBJPROP_PP(struc);
|
myht = Z_OBJPROP_PP(struc);
|
||||||
if (level > 1) {
|
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);
|
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);
|
efree(class_name);
|
||||||
if (myht) {
|
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) {
|
if (level > 1) {
|
||||||
php_printf("%*c", level - 1, ' ');
|
buffer_append_spaces(buf, level - 1);
|
||||||
}
|
}
|
||||||
php_printf ("))");
|
smart_str_appendl(buf, "))", 2);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PUTS ("NULL");
|
smart_str_appendl(buf, "NULL", 4);
|
||||||
break;
|
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])
|
/* {{{ proto mixed var_export(mixed var [, bool return])
|
||||||
Outputs or returns a string representation of a variable */
|
Outputs or returns a string representation of a variable */
|
||||||
PHP_FUNCTION(var_export)
|
PHP_FUNCTION(var_export)
|
||||||
{
|
{
|
||||||
zval *var;
|
zval *var;
|
||||||
zend_bool return_output = 0;
|
zend_bool return_output = 0;
|
||||||
|
smart_str buf = {0};
|
||||||
|
|
||||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &var, &return_output) == FAILURE) {
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &var, &return_output) == FAILURE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (return_output) {
|
php_var_export_ex(&var, 1, &buf TSRMLS_CC);
|
||||||
php_output_start_default(TSRMLS_C);
|
smart_str_0 (&buf);
|
||||||
}
|
|
||||||
|
|
||||||
php_var_export(&var, 1 TSRMLS_CC);
|
|
||||||
|
|
||||||
if (return_output) {
|
if (return_output) {
|
||||||
php_output_get_contents(return_value TSRMLS_CC);
|
RETVAL_STRINGL(buf.c, buf.len, 1);
|
||||||
php_output_discard(TSRMLS_C);
|
} else {
|
||||||
|
PHPWRITE(buf.c, buf.len);
|
||||||
}
|
}
|
||||||
|
smart_str_free(&buf);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue