php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #64297 Segfault after allowed memory exhausted
Submitted: 2013-02-25 13:48 UTC Modified: 2016-07-14 12:09 UTC
Votes:7
Avg. Score:4.6 ± 0.7
Reproduced:7 of 7 (100.0%)
Same Version:5 (71.4%)
Same OS:7 (100.0%)
From: jille at hexon dot cx Assigned: dmitry (profile)
Status: Closed Package: Reproducible crash
PHP Version: 5.4.12 OS: Linux
Private report: No CVE-ID: None
 [2013-02-25 13:48 UTC] jille at hexon dot cx
Description:
------------
PHP crashes with a segmentation fault when we allocate more memory than allowed.

This happens in 5.4.9 as well as 5.4.12. (No other versions tested.) The only 

Different SAPI's yield different behaviours:
* cli prints the OOM-error and sends it to syslog and segfaults immediately.
* cli in gdb or valgrind doesn't print it but syslogs and segfaults the same.
* apache2handler immediately sends the OOM-error to syslog but gives an error ("Cannot redeclare class Bummer") and segfaults afterwards on the next request to that child.

The class Bummer is included from our auto_prepend_file and I'm sure it isn't accidentally included twice. Funny thing is sometimes the error is about a different class (sometimes not even one that was loaded by the auto_prepend_file but just with a require()) so my guess would be some kind of memory corruption.

I can reproduce this reliably but failed to create a small reproduction script and unfortunately can't publish the source of our libraries.

Actual result:
--------------
The OOM-error:
PHP Fatal error:  Allowed memory size of 1073741824 bytes exhausted (tried to allocate 32 bytes) in /path/to/libs/bpm.lib on line 3190

GDB:
Program received signal SIGSEGV, Segmentation fault.
_zend_mm_free_int (heap=0xfb0510, p=0x403aeda8)
    at /tmp/php-5.4.12/Zend/zend_alloc.c:2071
2071		size = ZEND_MM_BLOCK_SIZE(mm_block);
(gdb) bt
#0  _zend_mm_free_int (heap=0xfb0510, p=0x403aeda8)
    at /tmp/php-5.4.12/Zend/zend_alloc.c:2071
#1  0x00000000007a3992 in destroy_op_array (op_array=0x11f1640)
    at /tmp/php-5.4.12/Zend/zend_opcode.c:356
#2  0x00000000007bb288 in zend_hash_destroy (ht=0xfb0e20)
    at /tmp/php-5.4.12/Zend/zend_hash.c:560
#3  0x00000000007ad491 in zend_shutdown () at /tmp/php-5.4.12/Zend/zend.c:822
#4  0x000000000074ec4a in php_module_shutdown ()
    at /tmp/php-5.4.12/main/main.c:2365
#5  0x0000000000433c07 in main (argc=5, argv=0x7fffffffe648)
    at /tmp/php-5.4.12/sapi/cli/php_cli.c:1379

$ valgrind ./sapi/cli/php /path/to/memcrash.php
==5742== Memcheck, a memory error detector
==5742== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==5742== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==5742== Command: ./sapi/cli/php /path/to/memcrash.php
==5742== 
==5742== Conditional jump or move depends on uninitialised value(s)
==5742==    at 0x4E3B4E0: inflateReset2 (in /lib/x86_64-linux-gnu/libz.so.1.2.3.4)
==5742==    by 0x4E3B5D8: inflateInit2_ (in /lib/x86_64-linux-gnu/libz.so.1.2.3.4)
==5742==    by 0x4E364F5: uncompress (in /lib/x86_64-linux-gnu/libz.so.1.2.3.4)
==5742==    by 0x71E239: mmc_unpack_value (memcache_pool.c:337)
==5742==    by 0x723CF3: mmc_server_read_value (memcache_ascii_protocol.c:189)
==5742==    by 0x720732: mmc_pool_select (memcache_pool.c:1584)
==5742==    by 0x7211A7: mmc_pool_run (memcache_pool.c:1670)
==5742==    by 0x719635: zif_memcache_get (memcache.c:1669)
==5742==    by 0x853B58: zend_do_fcall_common_helper_SPEC (zend_vm_execute.h:642)
==5742==    by 0x80E00E: execute (zend_vm_execute.h:410)
==5742==    by 0x7AEF56: zend_execute_scripts (zend.c:1315)
==5742==    by 0x74EEE2: php_execute_script (main.c:2492)
==5742== 
==5742== Invalid read of size 8
==5742==    at 0x78717D: _zend_mm_free_int (zend_alloc.c:2071)
==5742==    by 0x7A3991: destroy_op_array (zend_opcode.c:356)
==5742==    by 0x7BB287: zend_hash_destroy (zend_hash.c:560)
==5742==    by 0x7AD490: zend_shutdown (zend.c:822)
==5742==    by 0x74EC49: php_module_shutdown (main.c:2365)
==5742==    by 0x433C06: main (php_cli.c:1379)
==5742==  Address 0x500031c0 is not stack'd, malloc'd or (recently) free'd
==5742== 
==5742== 
==5742== Process terminating with default action of signal 11 (SIGSEGV)
==5742==  Access not within mapped region at address 0x500031C0
==5742==    at 0x78717D: _zend_mm_free_int (zend_alloc.c:2071)
==5742==    by 0x7A3991: destroy_op_array (zend_opcode.c:356)
==5742==    by 0x7BB287: zend_hash_destroy (zend_hash.c:560)
==5742==    by 0x7AD490: zend_shutdown (zend.c:822)
==5742==    by 0x74EC49: php_module_shutdown (main.c:2365)
==5742==    by 0x433C06: main (php_cli.c:1379)
==5742==  If you believe this happened as a result of a stack
==5742==  overflow in your program's main thread (unlikely but
==5742==  possible), you can try to increase the size of the
==5742==  main thread stack using the --main-stacksize= flag.
==5742==  The main thread stack size used in this run was 8388608.
==5742== 
==5742== HEAP SUMMARY:
==5742==     in use at exit: 7,524,625 bytes in 20,150 blocks
==5742==   total heap usage: 2,020,371 allocs, 2,000,221 frees, 1,589,606,462 bytes allocated
==5742== 
==5742== LEAK SUMMARY:
==5742==    definitely lost: 201,072 bytes in 3,591 blocks
==5742==    indirectly lost: 3,960,481 bytes in 2,926 blocks
==5742==      possibly lost: 82,068 bytes in 53 blocks
==5742==    still reachable: 3,281,004 bytes in 13,580 blocks
==5742==         suppressed: 0 bytes in 0 blocks
==5742== Rerun with --leak-check=full to see details of leaked memory
==5742== 
==5742== For counts of detected and suppressed errors, rerun with: -v
==5742== Use --track-origins=yes to see where uninitialised values come from
==5742== ERROR SUMMARY: 4 errors from 2 contexts (suppressed: 2 from 2)
Segmentation fault

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-02-25 14:56 UTC] laruence@php.net
-Status: Open +Status: Feedback
 [2013-02-25 14:56 UTC] laruence@php.net
please remove the memcache extension then test it again.
 [2013-02-25 15:51 UTC] jille at hexon dot cx
Removing the memcache extension doesn't help. (gdb output seems the same, do you want the new valgrind output? (Takes a while))
 [2013-02-25 15:51 UTC] jille at hexon dot cx
-Status: Feedback +Status: Open
 [2013-03-01 03:12 UTC] laruence@php.net
do you get the new valgrind log?

thanks
 [2013-03-01 03:12 UTC] laruence@php.net
-Status: Open +Status: Feedback
 [2013-03-01 08:15 UTC] jille at hexon dot cx
==30922== Memcheck, a memory error detector
==30922== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==30922== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==30922== Command: ./sapi/cli/php -d auto_prepend_file=auto_prepend_prepend.lib /data/www/htdocs/wheeler/daemons/daemon_wrapper 1023 live memcrash.php
==30922== 
==30922== Invalid read of size 8
==30922==    at 0x77954D: _zend_mm_free_int (zend_alloc.c:2071)
==30922==    by 0x795D61: destroy_op_array (zend_opcode.c:356)
==30922==    by 0x7AD657: zend_hash_destroy (zend_hash.c:560)
==30922==    by 0x79F860: zend_shutdown (zend.c:822)
==30922==    by 0x741019: php_module_shutdown (main.c:2365)
==30922==    by 0x433BE6: main (php_cli.c:1379)
==30922==  Address 0x4ca5d948 is not stack'd, malloc'd or (recently) free'd
==30922== 
==30922== 
==30922== Process terminating with default action of signal 11 (SIGSEGV)
==30922==  Access not within mapped region at address 0x4CA5D948
==30922==    at 0x77954D: _zend_mm_free_int (zend_alloc.c:2071)
==30922==    by 0x795D61: destroy_op_array (zend_opcode.c:356)
==30922==    by 0x7AD657: zend_hash_destroy (zend_hash.c:560)
==30922==    by 0x79F860: zend_shutdown (zend.c:822)
==30922==    by 0x741019: php_module_shutdown (main.c:2365)
==30922==    by 0x433BE6: main (php_cli.c:1379)
==30922==  If you believe this happened as a result of a stack
==30922==  overflow in your program's main thread (unlikely but
==30922==  possible), you can try to increase the size of the
==30922==  main thread stack using the --main-stacksize= flag.
==30922==  The main thread stack size used in this run was 8388608.
==30922== 
==30922== HEAP SUMMARY:
==30922==     in use at exit: 7,553,441 bytes in 20,136 blocks
==30922==   total heap usage: 2,020,750 allocs, 2,000,614 frees, 1,564,536,722 bytes allocated
==30922== 
==30922== LEAK SUMMARY:
==30922==    definitely lost: 203,536 bytes in 3,635 blocks
==30922==    indirectly lost: 4,029,186 bytes in 2,979 blocks
==30922==      possibly lost: 70,648 bytes in 43 blocks
==30922==    still reachable: 3,250,071 bytes in 13,479 blocks
==30922==         suppressed: 0 bytes in 0 blocks
==30922== Rerun with --leak-check=full to see details of leaked memory
==30922== 
==30922== For counts of detected and suppressed errors, rerun with: -v
==30922== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 2 from 2)
Segmentation fault
 [2013-03-01 08:15 UTC] jille at hexon dot cx
-Status: Feedback +Status: Open
 [2013-03-01 09:38 UTC] laruence@php.net
nothing serious, 

so the segufalt backtrace is the same as before?
 [2013-03-01 09:43 UTC] jille at hexon dot cx
Yes. Exactly the same.
 [2013-03-01 09:47 UTC] jille at hexon dot cx
(gdb) f 3
#3  0x000000000079f861 in zend_shutdown () at /tmp/php-5.4.12/Zend/zend.c:822
822		zend_hash_destroy(GLOBAL_FUNCTION_TABLE);
(gdb) f 2
#2  0x00000000007ad658 in zend_hash_destroy (ht=0xf9fe90)
    at /tmp/php-5.4.12/Zend/zend_hash.c:560
560				ht->pDestructor(q->pData);
(gdb) print *q
$5 = {h = 13860750752776937334, nKeyLength = 14, pData = 0x11d99b0, 
  pDataPtr = 0x0, pListNext = 0x11d9ab0, pListLast = 0x11d6fe0, pNext = 0x0, 
  pLast = 0x0, arKey = 0x7ffff7ed6f18 "udp_getsocket"}
(gdb) f 1
#1  0x0000000000795d62 in destroy_op_array (op_array=0x11d99b0)
    at /tmp/php-5.4.12/Zend/zend_opcode.c:356
356			efree(op_array->run_time_cache);
(gdb) print *op_array
$6 = {type = 2 '\002', function_name = 0x7ffff7fd4638 "udp_getSocket", 
  scope = 0x0, fn_flags = 134217728, prototype = 0x0, num_args = 0, 
  required_num_args = 0, arg_info = 0x0, refcount = 0x7ffff7fd5e20, 
  opcodes = 0x7ffff7fd7838, last = 17, vars = 0x7ffff7fd3fc8, last_var = 1, 
  T = 6, brk_cont_array = 0x0, last_brk_cont = 0, try_catch_array = 0x0, 
  last_try_catch = 0, static_variables = 0x7ffff7fd4e80, 
  this_var = 4294967295, filename = 0x7ffff7fd0ba0 "", line_start = 3, 
  line_end = 9, doc_comment = 0x0, doc_comment_len = 0, 
  early_binding = 4294967295, literals = 0x7ffff7fd4fd0, last_literal = 8, 
  run_time_cache = 0x3a0f81a0, last_cache_slot = 2, reserved = {0x0, 0x0, 0x0, 
    0x0}}
(gdb) print *op_array->run_time_cache 
Cannot access memory at address 0x3a0f81a0
 [2016-07-14 12:09 UTC] dmitry@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: dmitry
 [2016-07-14 12:09 UTC] dmitry@php.net
Memory overflow handling in php 5 wasn't graceful, and might lead to undefined behavior during request shutdown.
This is fixed in PHP-7.0
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Fri Nov 22 09:01:25 2019 UTC