php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #25175 session.use_trans_sid causes ob_get_length() to return incorrect value
Submitted: 2003-08-20 07:05 UTC Modified: 2003-08-25 16:19 UTC
From: phpbug at paypc dot com Assigned:
Status: Not a bug Package: Session related
PHP Version: 4.3.2 OS: Linux 2.4
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: phpbug at paypc dot com
New email:
PHP Version: OS:

 

 [2003-08-20 07:05 UTC] phpbug at paypc dot com
Description:
------------
Very straightforward.

I have a preamble and postamble include on ALL of my main .php pages... which use ADODB session management, some PEAR, and other typical dynaweb goodies.

The Content-Length header is *ALWAYS* off by about 81 bytes, as in, the ob_get_length() is always smaller than the actual size of the content sent...

I've verified this with "netcat" - after trimming the headers from the reply, the content is 81 bytes larger than advertised in the Content-Length header.

I observed no change in behaviour after adding the ob_clean() call into my header file.

OTHERWISE, things work fine.

What's the deal?  Is Apache silently adding CRLF's?

I am NOT using the gzhandler or transparent compression here.  This is just straightforward output.

=Lord Apollyon=


Reproduce code:
---------------
The code for all of my index.php's consist of the following:

<?PHP
include_once 'db_header.inc';
................
include_once 'db_footer.inc';
?>

db_header.inc:

<?php
$start_time=gettimeofday();
ob_clean();   // paranoid and desperate
ob_start();
header("Connection-Type: Keep-Alive");
?>

db_footer.inc contains:

<?PHP
if ($LOGGING) 
{
    $LOG->close();
	$LOGGING=FALSE;
}
header('Content-Length: ' . ob_get_length());
ob_end_flush();
?>

Note: there are no blank lines at the beginning of my *.inc or *.php files.

Expected result:
----------------
I would expect Content-Length to reflect the actual output size.



Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2003-08-20 22:54 UTC] sniper@php.net
try this script:

<?php ob_start(); ?>
foo
<?php

header("Connection-Type: Keep-Alive");
header('Content-Length: ' . ob_get_length());
ob_end_flush();
echo ob_get_length();

?>

And access it with this command:

# lynx -head lynx -dump -head http://localhost/test.php

I get this (correct) output:

HTTP/1.1 200 OK
Date: Thu, 21 Aug 2003 03:52:44 GMT
Server: Apache/1.3.27 (Unix) PHP/4.3.3RC5-dev
X-Powered-By: PHP/4.3.3RC5-dev
Connection-Type: Keep-Alive
Content-Length: 4
Connection: close
Content-Type: text/html


 [2003-08-21 00:10 UTC] moriyoshi@php.net
> Set-Cookie: PHPSESSID=2989258979bd07405999448563ef4bfc; path=/

Perhaps you seem to have enabled session.use_trans_sid.
If so, first turn it off before trying the above script provided by sniper.
 [2003-08-21 04:31 UTC] phpbug at paypc dot com
OK, let me put forth some declarations so we're talking apples and apples.

My test method:

echo -e "GET /legal/tester.php HTTP/1.1\r\nHost: 127.0.0.1\r\n" | nc 127.0.0.1 80 > dump

I wish to eliminate any possible "post-processing" or browser-variations.

IE: "nc" is netcat, a commonly available network tool.

OK, onto the results of my tests.

I copied and pasted sniper's code *EXACTLY* as presented, with whitespaces and line spacing as entered.  I obtained identical results with both lynx and my netcat method, though lynx probably doesn't support HTTP/1.1 because there was an additional header.

With Lynx Version 2.8.3rel.1:

HTTP/1.1 200 OK
Date: Thu, 21 Aug 2003 09:10:16 GMT
Server: Apache/1.3.27 Ben-SSL/1.48
Connection-Type: Keep-Alive
Content-Length: 4
Connection: close   <<<<<<<<<<<<< Additional header
Content-Type: text/html

With netcat:

HTTP/1.1 200 OK
Date: Thu, 21 Aug 2003 09:10:55 GMT
Server: Apache/1.3.27 Ben-SSL/1.48
Connection-Type: Keep-Alive
Content-Length: 4
Content-Type: text/html

In comparing the actual bytes sent over the wire against the advertised content-length, the Content-Length header is correct.

If you wish to inspect my PHP build and setup configuration, you may do so at: <http://hollywood.paypc.com/config4phpbugmasters>

(I will be removing this after 24 hours.)

And yes, it's pretty loaded.  And yes, trans_sid is enabled, but in all of my test harnesses which employ sessions, I've enabled cookies - and they are created/used by the browsers involved.

******* AHHHHHHAAAA *******

Arigatoo gozaimashita to Moriyoshi-san for cautioning me to turn on trans_sid, because when I disable it in my global php.ini, the discrepancy disappears!

For my "complex" web-application which formerly reported bad sizing, I received the following header (after turning off trans_sid):

----------------------------
HTTP/1.1 200 OK
Date: Thu, 21 Aug 2003 09:20:47 GMT
Server: Apache/1.3.27 Ben-SSL/1.48
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: PHPSESSID=a1c8bfb3f409580e57206d7c19eac473; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Content-Length: 2825
Content-Type: text/html
--------------------------------

And doing a wc -c on the content-portion matches this size exactly (with my netcat test).

Third-party validation via usage of <http://www.ircache.net/cgi-bin/cacheability.py> confirms an exact match of advertised Content-Length and what's actually received.

And lastly, and most importantly, the IE "hang" bug while accessing this web application via an intranet is gone.

OK, fine, trans_sid broke it.  Why?  And should it have?  I'm suspicious that the Esteemed Moriyoshi-san nailed this specific setting in advance, as if to suspect it being a potential cause for buggage.

Inquiring minds want to know - if it's by design, please add it to the documentation and FAQ.  I know alot of things about the ob_ functions are unusual and cause some people hardship (of their own making).  This one came out of left field.

=Apollyon=
 [2003-08-21 04:33 UTC] phpbug at paypc dot com
*ARGH* I hate "thinkoes" -- it should be obvious from context (and perusing my phpconfig) that I've TURNED OFF enable_trans_sid, not turned it on.

Upon re-reading my posting (naturally AFTER I'd hit submit), I noted the think-o.

My apologies.  

=Apollyon=
 [2003-08-22 13:48 UTC] moriyoshi@php.net
Technically, this is not a bug. Please see the following description.

trans-sid (aka URL rewriter) utilises output buffering facility and it virtually works as a top level output buffer handler in the hanlder stack. Thus ob_get_length() might not reflect the actual length of the content being sent to the user-agent because trans-sid handler automatically rewrites all URL referrers of the tags that are specified by url_rewriter.tags in your php.ini so they contains session identifiers if the content includes any one of those tags. So, in any case ob_get_length() returns the size of the intact content, on which no URL transformation is applied yet. The same thing applies to zlib.output_compression.

Then let me mark this PR bogus since this is not a bug in PHP. But this behaviour is rather confusing and will be addressed in the future versions.

BTW, how on earth did you know I'm Japanese? :)
 [2003-08-23 04:47 UTC] phpbug at paypc dot com
ARGH... I had just rebuilt PHP (from the snapshot) and Apache.... the problem still exists, though Moriyoshi-san pretty much pre-confirmed it - I should have checked back here before embarking on a web-server rebuild.  No worries.

When I have trans_sid enabled, the discrepancy crops up again, but you knew that.

I have not plumbed the depths of Zend and the output buffering part of PHP, but I'm surprised that this URL rewriting occurs at a level "higher" than that which obtaining the length of that buffer to be sent can be determined.

I can understand the issues with the gzhandler readily enough - that's a "final pass" process which takes the entire output and compresses it prior to its flight to the client.

If the gzhandler breaks trans_sid (or vice-versa), then I suspect someone make a bizarre design decision about where these various parts need to fit together.

Transformation passes like trans_sid should be made before transport passes (like gzhandler) and functions which determine buffer length get at things.  

I would like to think that this is NOT a Bogus bug, but a bug whose fix is at least in the pipeline to be addressed.  While it's easier to understand how the gzhandler problems would be an especially hard case to resolve, the ob_get_length() one shouldn't be.  

Or is the problem one where the URL rewriting happens while the data is actually IN-FLIGHT to the web-browser, after a possible response from the browser *AFTER* the header has been sent, but before the content?

If the PHP team intends to never address this as a decision of policy, then retire this bug and place warnings into the documentation and FAQ.  

But if you intend to resolve it, I would think it retains some value to leave it as an open issue for future (and possibly unspecified) future resolution.

Apollyon
 [2003-08-25 16:19 UTC] moriyoshi@php.net
As the documentation says, ob_get_length() returns the length of the current output buffer. It's not supposed to return the length of the actual HTTP content, while it's also the case those values are often the same. I'm afraid, that you cannot do it right with the current version of PHP.

One can say this is a design issue, but it's not an actual bug, although we can deem it as a feature request. So it'd be better to file a new report for such a function that returns the content length than turn this report into a request, which may cause confusion on other people using this bug database.

Thanks.

 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Oct 17 21:01:27 2024 UTC