php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #21478 Zend/zend_alloc.c :: shutdown_memory_manager produces segfault
Submitted: 2003-01-06 19:00 UTC Modified: 2003-06-01 12:54 UTC
From: pollita@php.net Assigned:
Status: Closed Package: Scripting Engine problem
PHP Version: 5.0.0-dev OS: linux
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: pollita@php.net
New email:
PHP Version: OS:

 

 [2003-01-06 19:00 UTC] pollita@php.net
This is a note to myself to fix this.

When stream_get_filters(true) is called between stream_register_filter() and stream_fitler_(ap|pre)pend(), engine will segfault on script exit.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2003-01-07 00:04 UTC] pollita@php.net
It seems this error does not occour as a direct result of stream_get_filters but is instead coincidental.

I was testing code in the streams/filters implementation in PHP-CVS using the following script:

<?php
/* Define our filter class */
class rot13_filter extends php_user_filter {
  function read($length) {
    $tempstr = parent::read($length);
    for($i = 0; $i < strlen($tempstr); $i++)
      if (($tempstr[$i] >= 'A' AND $tempstr[$i] <= 'M') OR
          ($tempstr[$i] >= 'a' AND $tempstr[$i] <= 'm')) $tempstr[$i] = chr(ord($tempstr[$i]) + 13);
      else if (($tempstr[$i] >= 'N' AND $tempstr[$i] <= 'Z') OR
               ($tempstr[$i] >= 'n' AND $tempstr[$i] <= 'z')) $tempstr[$i] = chr(ord($tempstr[$i]) - 13);
    return $tempstr;
  }

  function write($data) {
    for($i = 0; $i < strlen($data); $i++)
      if (($data[$i] >= 'A' AND $data[$i] <= 'M') OR
          ($data[$i] >= 'a' AND $data[$i] <= 'm')) $data[$i] = chr(ord($data[$i]) + 13);
      else if (($data[$i] >= 'N' AND $data[$i] <= 'Z') OR
               ($data[$i] >= 'n' AND $data[$i] <= 'z')) $data[$i] = chr(ord($data[$i]) - 13);
    return parent::write($data);
  }
}

var_dump(stream_get_filters(true));

/* Register our filter with PHP */
stream_register_filter("rot13", "rot13_filter")
    or die("Failed to register filter");

var_dump(stream_get_filters(true));

$fp = fopen("foo-bar.txt","w");

stream_filter_append($fp, "string.rot13");
stream_filter_append($fp, "string.toupper");
stream_filter_append($fp, "rot13");

var_dump(stream_get_filters(true));
fwrite($fp,"This is a test.\n");

fclose($fp);

readfile("foo-bar.txt");
print "\n\n";
?>

And discovered a consistently reproducable crash upon script exit.  Oddly, compiling with --enable-debug causes the segfault to stop occouring.  (Making a backtrace difficult)

After exploration I discovered that commenting out one of the occourances of stream_get_filters() would prevent the segfault so I believed the fault to be in that function.

But here's the wierd twist:

Turns out that if you do something as innocuous as add:

$myvar = "";

to the end of that script, the segfault goes away.

After putting in a series of watches I tracked the segfault down to the call to: ZEND_DO_FREE(ptr) on line 462 of Zend/zend_alloc.c in shutdown_memory_manager.

The value of ptr looks reasonable and is in the same neighborhood as other calls in the i/j loops.

I wish I could give you something better to work with but this is a seriously elusive heisenbug.

I'll continue to explore the code locally, but I don't pretend to know the Zend engine as well as many of you others.

- pollita@php.net



CVS: 2003-01-06
./configure --without-mysql --disable-cgi
 [2003-01-07 09:07 UTC] iliaa@php.net
#0  0x40108fdd in chunk_free (ar_ptr=0x4019ff80, p=0x82ca930) at malloc.c:3131
#1  0x40108ea3 in __libc_free (mem=0x82ca938) at malloc.c:3054
#2  0x080bf61c in shutdown_memory_manager (silent=0, clean_cache=0)
    at /home/rei/PHP_CVS/php4/Zend/zend_alloc.c:462
#3  0x080a94e6 in php_request_shutdown (dummy=0x0) at /home/rei/PHP_CVS/php4/main/main.c:1069
#4  0x080e25a6 in main (argc=2, argv=0xbffff764) at /home/rei/PHP_CVS/php4/sapi/cli/php_cli.c:801
#5  0x400b5f5c in __libc_start_main (main=0x80e1ca0 <main>, argc=2, ubp_av=0xbffff764,
    init=0x8059428 <_init>, fini=0x80e288c <_fini>, rtld_fini=0x4000ce30 <_dl_fini>,
    stack_end=0xbffff75c) at ../sysdeps/generic/libc-start.c:129

Here is the backtrace of the crash, what is indeed most curious is that the crash ONLY occurs when PHP is compiled with -0N optimization flags.
 [2003-03-18 10:58 UTC] black@php.net
Program received signal SIGSEGV, Segmentation fault.
_zval_ptr_dtor (zval_ptr=0x73) at /root/src/php4-standard/Zend/zend_execute_API.c:289
289             (*zval_ptr)->refcount--;
(gdb) bt
#0  _zval_ptr_dtor (zval_ptr=0x73) at /root/src/php4-standard/Zend/zend_execute_API.c:289
#1  0x4036240c in zend_hash_destroy (ht=0x8138f14) at /root/src/php4-standard/Zend/zend_hash.c:543
#2  0x4035d1e2 in _zval_dtor (zvalue=0x809fb1c) at /root/src/php4-standard/Zend/zend_variables.c:51
#3  0x40356fb9 in _zval_ptr_dtor (zval_ptr=0x8147a10) at /root/src/php4-standard/Zend/zend_execute_API.c:291
#4  0x4036240c in zend_hash_destroy (ht=0x4040f56c) at /root/src/php4-standard/Zend/zend_hash.c:543
#5  0x40356db0 in shutdown_executor () at /root/src/php4-standard/Zend/zend_execute_API.c:186
#6  0x4035e0be in zend_deactivate () at /root/src/php4-standard/Zend/zend.c:649
#7  0x40337cb3 in php_request_shutdown (dummy=0x0) at /root/src/php4-standard/main/main.c:942
#8  0x4036e9fe in apache_php_module_main (r=0x8104d44, display_source_mode=0) at /root/src/php4-standard/sapi/apache/sapi_apache.c:61
#9  0x4036f3b7 in send_php (r=0x8104d44, display_source_mode=0, filename=0x0) at /root/src/php4-standard/sapi/apache/mod_php4.c:610
#10 0x4036f565 in send_parsed_php (r=0x8104d44) at /root/src/php4-standard/sapi/apache/mod_php4.c:625
#11 0x08053b34 in ap_invoke_handler ()
#12 0x0806368c in ap_some_auth_required ()
#13 0x080636e8 in ap_process_request ()
#14 0x0805ce2b in ap_child_terminate ()
#15 0x0805cfbc in ap_child_terminate ()
#16 0x0805d0d9 in ap_child_terminate ()
#17 0x0805d5b5 in ap_child_terminate ()
#18 0x0805dcbd in main ()
#19 0x400dfa51 in __libc_start_main () from /lib/libc.so.6


this would be the same as the description to/for the problem described here... i suspect that it has something to do with either not cleaning ob_start() buffers manually, or something with header("Location: ") (or a combination of both).. that atleast is regarding my problem

this backtrace is from the latest php4-200303181430, but i can also reproduce it on the -STABLE branch (ill post the bt later).
 [2003-03-26 18:42 UTC] pollita@php.net
Another reproducing script:

Happens with HEAD as of today.
./configure --with-gd --with-zlib-dir=/usr --with-mysql --enable-ftp --enable-bcmath --enable-maintainer-zts --enable-sockets --with-gmp=/usr --with-imap --with-imap-ssl=/usr/src/openssl-0.9.6g

I've gotten similar results with simpler ./configure lines and simpler scripts, but this is the configuration that is immediately available to me.

#!sapi/cli/php
<?php
class debugfilter extends php_user_filter {
  function filter($in, $out, &$consumed, $closing) {
    while ($bucket = stream_bucket_make_writeable($in)) {
      $bucket->data = strtoupper($bucket->data);
      stream_bucket_append($out, $bucket);
      $consumed += strlen($bucket->data);
    }
    return PSFS_PASS_ON;
  }
}


stream_register_filter("myfilter","debugfilter");

$fp = fopen("test.txt","w");
stream_filter_append($fp, "myfilter");
stream_filter_append($fp, "myfilter");
stream_filter_append($fp, "myfilter");
fwrite($fp, "This is a test.\n");
print "Done.\n";
fclose($fp);
// Uncommenting the following 'print' line causes the segfault to stop occuring
// print "2\n";  
readfile("test.txt");
?>

 [2003-06-01 12:54 UTC] helly@php.net
This bug has been fixed in CVS.

In case this was a PHP problem, snapshots of the sources are packaged
every three hours; this change will be in the next snapshot. You can
grab the snapshot at http://snaps.php.net/.
 
In case this was a documentation problem, the fix will show up soon at
http://www.php.net/manual/.

In case this was a PHP.net website problem, the change will show
up on the PHP.net site and on the mirror sites in short time.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu May 16 23:01:30 2024 UTC