]> granicus.if.org Git - php/commitdiff
Fix a bug when var_export() causes a fatal error that could inadvertently display...
authorScott MacVicar <scottmac@php.net>
Fri, 9 Jul 2010 21:11:37 +0000 (21:11 +0000)
committerScott MacVicar <scottmac@php.net>
Fri, 9 Jul 2010 21:11:37 +0000 (21:11 +0000)
Examples include, memory limit, execution time and recursion.

ext/standard/php_var.h
ext/standard/tests/general_functions/var_export_error2.phpt
ext/standard/tests/general_functions/var_export_error3.phpt
ext/standard/var.c

index ce4db5bdf49b1686f3967962c1c786e6b633ba2f..91026f804b34885e63cbda6c9fcb2295d2a57497 100644 (file)
@@ -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;
index 93d0dc16463827062955fcd1418e12346ccea9e5..2b306696a692b170855dbb6fa58c4d47cf989f5e 100644 (file)
@@ -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
index 4ad5121682b5690c154909f48dab5c189e49c3b2..03ed496aca5f81dfdd8af8215a3df7c7517098eb 100644 (file)
@@ -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
index 05bdcb003aa06257230f14cdb790643e96633c38..d0482f0d955a3b6b589ab5142e4b01e3a3079359 100644 (file)
@@ -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);
 }
 /* }}} */