php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #51244 segv on zend_mm_search_large_block
Submitted: 2010-03-09 05:17 UTC Modified: 2010-03-09 10:17 UTC
From: wataruhirayama at gmail dot com Assigned:
Status: Not a bug Package: Unknown/Other Function
PHP Version: 5.3.2 OS: CentOS release 5.4
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: wataruhirayama at gmail dot com
New email:
PHP Version: OS:

 

 [2010-03-09 05:17 UTC] wataruhirayama at gmail dot com
Description:
------------
I create a extension to use my function written in C++ from PHP.
# I don't talk about the details of my extionsion because it is proprietary.

configure parameters:
./configure --with-apxs2=/usr/local/apache2/bin/apxs \
 --enable-sysvsem \
 --enable-maintainer-zts \
 --with-tsrm-pthreads

My extension is multi-threaded so PHP is the same.

When I pass hundreds of data to my extension, hundreds of threads are created, and thousands of emallocs are called (though small size each).
# Physical memory = 256MB, Swap = 512MB

The first time I do it, it normally succeed.
But the second time, segmentation fault raised.

$ sudo gdb /usr/local/apache2/bin/httpd
(gdb) run -X -f /usr/local/apache2/conf/httpd.conf
---snip---
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x32ebb90 (LWP 5878)]
0x013b3d07 in zend_mm_search_large_block (heap=0x9a8cd70, true_size=16)
    at /usr/local/src/php-5.3.2/Zend/zend_alloc.c:1792
1792            while ((p = p->child[p->child[0] != NULL])) {
(gdb) bt
#0  0x013b3d07 in zend_mm_search_large_block (heap=0x9a8cd70, true_size=16)
    at /usr/local/src/php-5.3.2/Zend/zend_alloc.c:1792
#1  0x013b3e34 in _zend_mm_alloc_int (heap=0x9a8cd70, size=1)
    at /usr/local/src/php-5.3.2/Zend/zend_alloc.c:1852
#2  0x013b4d51 in _emalloc (size=1)
    at /usr/local/src/php-5.3.2/Zend/zend_alloc.c:2340
#3  0x013b514f in _estrdup (s=0x706abf0 "")
    at /usr/local/src/php-5.3.2/Zend/zend_alloc.c:2481
#4  0x06fb31ef in [snip] (arg=0x8cde23c)
    at [snip]
#5  0x0098273b in start_thread () from /lib/libpthread.so.0
#6  0x00900cfe in clone () from /lib/libc.so.6
(gdb) p p
$1 = (zend_mm_free_block *) 0x0
(gdb) p *heap
$2 = {use_zend_alloc = 1, _malloc = 0, _free = 0, _realloc = 0,
  free_bitmap = 0, large_free_bitmap = 131072, block_size = 262144,
  compact_size = 2097152, segments_list = 0x9a8cfd0, storage = 0x9a8cd60,
  real_size = 262144, real_peak = 262144, limit = 134217728, size = 10340,
  peak = 10340, reserve_size = 8192, reserve = 0x9a8cfe0, overflow = 0,
  internal = 0, cached = 76, cache = {0x0, 0x0, 0x9a8efe0, 0x0, 0x0, 0x0, 0x0,
    0x0, 0x0, 0x9a8eff8, 0x0 <repeats 22 times>}, free_buckets = {0x9a8ce38,
    0x9a8ce38, 0x9a8ce40, 0x9a8ce40, 0x9a8ce48, 0x9a8ce48, 0x9a8ce50,
    0x9a8ce50, 0x9a8ce58, 0x9a8ce58, 0x9a8ce60, 0x9a8ce60, 0x9a8ce68,
    0x9a8ce68, 0x9a8ce70, 0x9a8ce70, 0x9a8ce78, 0x9a8ce78, 0x9a8ce80,
    0x9a8ce80, 0x9a8ce88, 0x9a8ce88, 0x9a8ce90, 0x9a8ce90, 0x9a8ce98,
    0x9a8ce98, 0x9a8cea0, 0x9a8cea0, 0x9a8cea8, 0x9a8cea8, 0x9a8ceb0,
    0x9a8ceb0, 0x9a8ceb8, 0x9a8ceb8, 0x9a8cec0, 0x9a8cec0, 0x9a8cec8,
    0x9a8cec8, 0x9a8ced0, 0x9a8ced0, 0x9a8ced8, 0x9a8ced8, 0x9a8cee0,
    0x9a8cee0, 0x9a8cee8, 0x9a8cee8, 0x9a8cef0, 0x9a8cef0, 0x9a8cef8,
    0x9a8cef8, 0x9a8cf00, 0x9a8cf00, 0x9a8cf08, 0x9a8cf08, 0x9a8cf10,
    0x9a8cf10, 0x9a8cf18, 0x9a8cf18, 0x9a8cf20, 0x9a8cf20, 0x9a8cf28,
    0x9a8cf28, 0x9a8cf30, 0x9a8cf30}, large_free_buckets = {
    0x0 <repeats 32 times>}, rest_buckets = {0x9a8cfb8, 0x9a8cfb8}}
(gdb) p heap->large_free_buckets
$3 = {0x0 <repeats 32 times>}

I don't know this is the right way, but just add NULL check and nothing happened. 

$ git diff HEAD^
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
index dac5454..707f75a 100644
--- a/Zend/zend_alloc.c
+++ b/Zend/zend_alloc.c
@@ -1789,6 +1789,7 @@ static zend_mm_free_block *zend_mm_search_large_block(zend

        /* Search for smallest "large" free block */
        best_fit = p = heap->large_free_buckets[index + zend_mm_low_bit(bitmap)]
+       if(!best_fit) return NULL;
        while ((p = p->child[p->child[0] != NULL])) {
                if (ZEND_MM_FREE_BLOCK_SIZE(p) < ZEND_MM_FREE_BLOCK_SIZE(best_fi
                        best_fit = p;



Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-03-09 10:17 UTC] derick@php.net
-Status: Open +Status: Bogus
 [2010-03-09 10:17 UTC] derick@php.net
If you can't provide code, we can't help you.
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Thu Jul 17 14:04:04 2025 UTC