php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #21210 include() or require() cause conflicts with session, even with no output
Submitted: 2002-12-26 20:19 UTC Modified: 2002-12-28 10:38 UTC
Votes:1
Avg. Score:4.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: antispam at theapotek dot com Assigned:
Status: Not a bug Package: Session related
PHP Version: 4.2.3 OS: Linux 2.4.7
Private report: No CVE-ID: None
 [2002-12-26 20:19 UTC] antispam at theapotek dot com
Calling includes or requires seems to create header output, even if the includes or requires are blank. This conflicts with session handling in situations where the session is called as a result of logic-branches in the code.

I have encountered this issue on several different systems.

Here's the setup. 
Create an include file, called "include.php".
Put the following in it:
<?php
?>

Now, create a page with the following code:
<?php
include("include.php");

session_start();
session_register("SESSION");

if (!isset($SESSION)) {
        $SESSION["count"] = 0;
        print("<p>Counter initialized, please reload this page to see it increment</p>");
} 
else {
        print("<p>Waking up session $PHPSESSID</p>");
        $SESSION["count"]++;
}
print("<p>The counter is now $SESSION[count] </p>");
?>

run the page with all the code in the browser such that it includes the include file above.

Even though the include file does not write or generate a single header, the output I get is:
"Warning: Cannot send session cookie - headers already sent by (output started at include.php:1) in test.php on line 4

Warning: Cannot send session cache limiter - headers already sent (output started at include.php:1) in test.php on line 4

Counter initialized, please reload this page to see it increment

The counter is now 0 "

My observation is corroborated by the following note, found on the session_start() function manual page at php.net. 

############
As per <shadowflame at starpilot dot net>:
"If you are using an include page, such as a config or possibly common-functions page, that relies on session variables being pulled from the sesssion, remember to add the session_start() function _before_ you call the includes, or your session will not be called by the page..."

Any include or require called before you call session_start() will cause the initial session setup to fail, even if that include file contains only a comment! 

Here are scenarios:
include("blank_file.php");
session_start();

This works. However:

include("file_with_just_a_comment_in_it.php");
session_start();

Does not.

The recommended way to use session_start() is of course to put it at the top of the page. However, if, like me, you find yourself wanting to start a session only as a result of some previous logic, this avenue is closed to you. You will have to use ob_start() and related functions, and create a code mess. 

It will be a beautiful day when header conflicts are caused only by the layout of my code rather than PHP code cruft.
##############

As mentioned, I've encountered this on several different systems, so configure lines and php.ini doesn't seem to be too relevant. If you want build lines or php.ini, I'll send them on via e-mail.

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2002-12-26 20:24 UTC] rasmus@php.net
Do a 'od -c include.php' and see what is at the end of your included file.  I bet you have extra carriage returns.
 [2002-12-26 20:46 UTC] antispam at theapotek dot com
So I do indeed! Thanks.

The immediate problem is solved; however, it seems strange to me that carriage returns should be causing "header like" output. Wouldn't it make more sense to make the require and include functions function not generate output from extraneous whitespace?
 [2002-12-26 21:14 UTC] rasmus@php.net
No, it would be a really bad idea to have PHP swallow up whitespace and other chars.  And any http body output, including whitespace, must be preceded by the HTTP headers, so PHP has to force them out.
 [2002-12-26 23:07 UTC] antispam at theapotek dot com
Understood. However, what makes this appear like a bug rather than a feature is that once a session is successfully registered, the code works as suspected, carriage returns and all. It's only in the very first initial session_start() that the problem appears, which is weird if, as you suggest, the problem simply has to remain in PHP. How come PHP can read cookies fine even if preceded by carriage returns or other whitespace, but cannot set cookies if preceded by carriage returns or other whitespace junk? I was under the impression both operations are performed in the headers, and if that's the case, and one works fine with whitespace preceding it, and the other doesn't, that would seem to indicate that this is a bug and not a feature.

I just think it's odd that I have to eliminate all comments and blank lines in a PHP include file if I want to use sessions later in the document.
 [2002-12-26 23:08 UTC] antispam at theapotek dot com
BTW, I have the problem now WITHOUT any carriage returns in the include file.
 [2002-12-26 23:10 UTC] rasmus@php.net
When starting a new session we need to set a cookie which happens in the response headers.  When simply reading a cookie we get that cookie out of the request headers.  That's a completely different operation and is done before you even start executing the script, so it is done long before the include.

And you only have to eliminate blank lines outside of PHP tags in include files.  You can have as many blank lines or PHP comments as you want in include files.
 [2002-12-26 23:11 UTC] rasmus@php.net
Email me your include file as an attachment please or put it up online somewhere so I can see it.
 [2002-12-28 10:38 UTC] antispam at theapotek dot com
Rasmus,

After looking through your generous answers, I realize I did not fully understand you until now. I was making tests with files like this...

<?php
/* A comment which seemed to be generating output */
?>

EOF, and reacting against the fact that a comment line was being spit out as a blank line in the headers (even though I saw no evidence of blank headers when I requested the script via "curl -I").

What you really meant was that whitespace OUTSIDE of the <?php?> tags were the problem. This makes much more sense, and I humbly withdraw the bug.

However, since this took the better part of two days to troubleshoot, I am wondering if it would be possible to have PHP generate some kind of warning, or at least a "real" header when something like this happens. For example, if I call the non-working version of the script via curl, with the -I option, I get this:
~>curl -I http://x.qyn/page.php/9/
HTTP/1.1 200 OK
Date: Sat, 28 Dec 2002 02:52:37 GMT
Server: Apache/1.3.27 (Darwin) PHP/4.1.2 mod_ssl/2.8.10 OpenSSL/0.9.6b
X-Powered-By: PHP/4.1.2
Set-Cookie: PHPSESSID=959cf428d5e5b199fbba1533d249fe4f; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Type: text/html
There is no indication that there is a blank header being sent, or any carriage returns or anything, before the Set-Cookie: header flies out. The return from curl -I is the same regardless of whether the script has extra carriage returns in an early include or not. Nor is there an error message generated by PHP, even with error_reporting set to ALL. In short, there is no indication that something is wrong except for the fact that the cookie doesn't actually get set. Which makes the programmer (me) use various browsers, clear cookies, reset cookie preferences, read hours and hours of postings about cookies, many of which remind you not to send a header before setting a cookie, returning to the code and seeing that sure enough, you aren't sending any results (as far as you can SEE) to the browser (no print statements, no header() calls) before the session_start or session_register gets called. You're stumped, and you find yourself finally filing a bug report which ends up wasting Rasmus Lerdorf's time.

Thank you so much for your time. Summary suggestion: A simple notice in the PHP parser for white space outside of <?php tags would save us a lot of time.

Kristofer Widholm
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Wed Sep 18 18:01:28 2024 UTC