]> granicus.if.org Git - php/commitdiff
Make sure output start filename is not freed early
authorNikita Popov <nikita.ppv@gmail.com>
Fri, 16 Oct 2020 15:23:10 +0000 (17:23 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Fri, 16 Oct 2020 15:27:52 +0000 (17:27 +0200)
As filenames are no longer interned, we need to keep a reference
to the zend_string to make sure it isn't freed.

To avoid a nominal source compatibility break, create a new member
in the globals.

Zend/tests/output_started_at_eval.phpt [new file with mode: 0644]
main/output.c
main/php_output.h

diff --git a/Zend/tests/output_started_at_eval.phpt b/Zend/tests/output_started_at_eval.phpt
new file mode 100644 (file)
index 0000000..4bb331c
--- /dev/null
@@ -0,0 +1,11 @@
+--TEST--
+Output start at eval()
+--FILE--
+<?php
+eval('echo "Foo\n";');
+header('Foo: Bar');
+?>
+--EXPECTF--
+Foo
+
+Warning: Cannot modify header information - headers already sent by (output started at %s(2) : eval()'d code:1) in %s on line %d
index c895d3856e441853d15f07822335c510dac20430..cffadede80811d82a17681c8d17b85e7589300e5 100644 (file)
@@ -103,16 +103,20 @@ static size_t (*php_output_direct)(const char *str, size_t str_len) = php_output
 static void php_output_header(void)
 {
        if (!SG(headers_sent)) {
-               if (!OG(output_start_filename)) {
+               if (!OG(output_start_filename_str)) {
                        if (zend_is_compiling()) {
-                               OG(output_start_filename) = ZSTR_VAL(zend_get_compiled_filename());
+                               OG(output_start_filename_str) = zend_get_compiled_filename();
                                OG(output_start_lineno) = zend_get_compiled_lineno();
                        } else if (zend_is_executing()) {
-                               OG(output_start_filename) = zend_get_executed_filename();
+                               OG(output_start_filename_str) = zend_get_executed_filename_ex();
                                OG(output_start_lineno) = zend_get_executed_lineno();
                        }
+                       if (OG(output_start_filename_str)) {
+                               zend_string_addref(OG(output_start_filename_str));
+                       }
 #if PHP_OUTPUT_DEBUG
-                       fprintf(stderr, "!!! output started at: %s (%d)\n", OG(output_start_filename), OG(output_start_lineno));
+                       fprintf(stderr, "!!! output started at: %s (%d)\n",
+                               ZSTR_VAL(OG(output_start_filename_str)), OG(output_start_lineno));
 #endif
                }
                if (!php_header()) {
@@ -190,6 +194,11 @@ PHPAPI void php_output_deactivate(void)
                }
                zend_stack_destroy(&OG(handlers));
        }
+
+       if (OG(output_start_filename_str)) {
+               zend_string_release(OG(output_start_filename_str));
+               OG(output_start_filename_str) = NULL;
+       }
 }
 /* }}} */
 
@@ -749,7 +758,7 @@ PHPAPI void php_output_set_implicit_flush(int flush)
  * Get the file name where output has started */
 PHPAPI const char *php_output_get_start_filename(void)
 {
-       return OG(output_start_filename);
+       return ZSTR_VAL(OG(output_start_filename_str));
 }
 /* }}} */
 
index 60f389b2b52ba239ad5508f0f0fdb4bdee726ce0..eba63e6039b9699ea1714112851d925121301889 100644 (file)
@@ -137,9 +137,10 @@ ZEND_BEGIN_MODULE_GLOBALS(output)
        zend_stack handlers;
        php_output_handler *active;
        php_output_handler *running;
-       const char *output_start_filename;
+       const char *output_start_filename; /* TODO: Unused, remove */
        int output_start_lineno;
        int flags;
+       zend_string *output_start_filename_str;
 ZEND_END_MODULE_GLOBALS(output)
 
 PHPAPI ZEND_EXTERN_MODULE_GLOBALS(output)