php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #25385 Segfault in Apache output compression
Submitted: 2003-09-03 13:15 UTC Modified: 2003-09-09 21:23 UTC
From: sroussey at network54 dot com Assigned:
Status: Closed Package: Output Control
PHP Version: 4.3.3 OS: Linux 2.4.20
Private report: No CVE-ID: None
 [2003-09-03 13:15 UTC] sroussey at network54 dot com
Description:
------------
While similar to bug#20551, this has a different backtrace.

Apache 1.3.27 error_log has a long list of segfaults (usually 3-12 a minute, but not every minute). Disabling output compression (via ob_start ('ob_gzhandler');) stops the segfaults.

This the backtrace:

#0  0x080a3de8 in _efree ()
#1  0x08093099 in sapi_add_header_ex ()
#2  0x080c2c9e in zif_ob_gzhandler ()
#3  0x080aa49c in call_user_function_ex ()
#4  0x0809c584 in php_end_ob_buffer ()
#5  0x0809c6d8 in php_end_ob_buffers ()
#6  0x0808ec05 in php_request_shutdown ()
#7  0x080c0b7b in apache_php_module_main ()
#8  0x08087d0e in ap_get_server_built ()
#9  0x08087eb1 in ap_get_server_built ()
#10 0x081c73bc in ap_invoke_handler ()
#11 0x081dc36a in ap_some_auth_required ()
#12 0x081929de in tsrm_strtok_r ()
#13 0x081c73bc in ap_invoke_handler ()
#14 0x081dc36a in ap_some_auth_required ()
#15 0x081dc5bb in ap_process_request ()
#16 0x081d3ded in ap_child_terminate ()
#17 0x081d3fe5 in ap_child_terminate ()
#18 0x081d438f in ap_child_terminate ()
#19 0x081d4e05 in ap_child_terminate ()
#20 0x081d51f2 in main ()
#21 0x420158f7 in __libc_start_main () from /lib/i686/libc.so.6

For reference, here is sapi_add_header_ex:

SAPI_API int sapi_add_header_ex(char *header_line, uint header_line_len, zend_bool duplicate, zend_bool replace TSRMLS_DC)
{
    sapi_header_line ctr = {0};
    int r;

    ctr.line = header_line;
    ctr.line_len = header_line_len;

    r = sapi_header_op(replace ? SAPI_HEADER_REPLACE : SAPI_HEADER_ADD,
            &ctr TSRMLS_CC);

    if (!duplicate)
        efree(header_line);

    return r;
}



In PHP_FUNCTION(ob_gzhandler) these are the relevant lines:

------------------------------------------------
switch (coding) {
case CODING_GZIP:
if (sapi_add_header("Content-Encoding: gzip", sizeof("Content-Encoding: gzip") - 1, 1) == FAILURE) {
return_original = 1;
}
if (sapi_add_header_ex("Vary: Accept-Encoding", sizeof("Vary: Accept-Encoding") - 1, 1, 0 TSRMLS_CC)==FAILURE) {
return_original = 1;
}
break;
case CODING_DEFLATE:
if (sapi_add_header("Content-Encoding: deflate", sizeof("Content-Encoding: deflate") - 1, 1) == FAILURE) {
return_original = 1;
}
if (sapi_add_header_ex("Vary: Accept-Encoding", sizeof("Vary: Accept-Encoding") - 1, 1, 0 TSRMLS_CC)==FAILURE) {
return_original = 1;
}
break;
------------------------------------------------

From my view, sapi_add_header_ex() should never be calling efree() since it is passed duplicate value of 1.

So why is it crashing there? What am I missing? How can I make it stop?

gcc version 3.2 20020903 (Red Hat Linux 8.0 3.2-7)



Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2003-09-03 13:53 UTC] sniper@php.net
You don't need to paste us the code, we know it already.
(providing patches is different)

Please provide a short example script that can be used to reproduce this bug.

 [2003-09-08 11:33 UTC] sroussey at network54 dot com
An example is impossible. This is not a 100% deterministic statistical event. It is 0% without the gzhandler stream. It is a little less than 1% with it. So it occurs thousands of times per hour. (And the Apache people wonder why php sites don?t move over to the threaded Apache 2.0 server?)

At any rate, if I had a repeatable piece of code I would have fixed it and posted a patch. Sadly I don?t. It could be that the user hit the stop button and the pipe broke and that caused some error somewhere that eventually crashed at this point. It doesn?t look like that, but you get the idea.

It was very difficult to get the backtrace here, since it only happens under load on the production servers and we have the MaxRequestsPerChild set to 200. (If we set it to a bigger number then the chance of the crash increases until the point of being unusable). Trying to gdb to running processes that have a short life and having the bug happen to that one, took a long time to get and repeat for verification. (In retrospect, I should have written a shell script to do it. Has anyone already done this?).

So anyhow, from my view, sapi_add_header_ex() should never be calling efree() since it is passed duplicate value of 1. So why is it crashing there? What am I missing? I got sort of stuck at this point. :(
 [2003-09-09 21:23 UTC] sniper@php.net
There was a typo in zlib.c:989, sapi_add_header_ex() call.
(the 3rd param should be 1, it was 0 :)

Fixed in CVS.

 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Dec 22 02:01:28 2024 UTC