php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #48228 Possible memory corruption when PHP compiled using GCC 4.3.x
Submitted: 2009-05-10 22:47 UTC Modified: 2009-05-27 21:14 UTC
Votes:1
Avg. Score:3.0 ± 0.0
Reproduced:0 of 0 (0.0%)
From: iddekingej at lycos dot com Assigned:
Status: Closed Package: Scripting Engine problem
PHP Version: 5.*, 6CVS (2009-05-27) OS: Linux 64bit gcc
Private report: No CVE-ID:
 [2009-05-10 22:47 UTC] iddekingej at lycos dot com
Description:
------------
The included example code was made for finding the reason php5.3RC2/apache2 crashed with some php website (the websie is not publicly available). The script didn't crash apache but failed differently.
The script should fail with a 'undefined variable', it does but it also displays the message "Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 140498868988960 bytes) in Unknown on line 0". (The large number is probably a memory location).

This error only happens in the following situation:
* as a web page (CLI works OK)
* restart apache
* Load the page and the memory exhausted message is displayed.
* Reload the page and no "memory exhausted" message

Software/machine:
* 64Bit amd
* Kubuntu  8.10
* Apache 2.2.9
* PHP(5.3RC2) compiled with : 
'./configure' '--enable-zip' '--enable-soap' '--enable-sockets' '--with-gd' '--with-pgsql' '--with-apxs2=/usr/bin/apxs2' '--with-gettext' '--enable-cli' '--enable-mbstring'





Reproduce code:
---------------
<?
function ex_handler($p_exception)
{
        ?> Error:<i><?=$p_exception->getMessage()?></i><br/><br/><?
}

function er_handler($p_errorno,$p_errstr,$p_errfile,$p_errline,$p_context)
{ 
   $l_exception=new Exception("Error $p_errorno at $p_errline in '$p_errfile':$p_errstr");     
   throw $l_exception;
}

  set_Exception_Handler("ex_handler");
  set_Error_Handler("er_handler",E_STRICT|E_WARNING|E_ALL|E_ERROR|E_NOTICE);
  class aa 
  {
    function check($p_a,$p_b,$p_c)
    {
      echo $p_a;
    }

    function dosome($p_b,$p_d,$p_e,$p_f,$p_g,$p_h)
    {
       return  $this->check(3,3,array("xx"=>$p_b,"xzx"=>$p_d,"xx"=>$p_e,"yy"=>$p_c));
    }
 }
  $l_aa=new aa();
  $l_aa->dosome('2',"33333333333333333","4","5",'sddddddddddddddddddddddd','ddddddddddddddddddd');
?>

Expected result:
----------------
* Undefined variable 


Actual result:
--------------
* Undefined variable 
* "Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 140498868988960 bytes) in Unknown on line 0". 

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-05-11 20:37 UTC] iddekingej at lycos dot com
Thanks, but the latest snapshot din't fix the problem.

I managed to debug apache and php and found the following:

The field alloc_globals->mm_heap->reserve_size is (wrongly) overwritten with some address while freeing memory.  This value contains therefore a large number.
Next, in zend_mm_shutdown the following code is executed

      if (heap->reserve_size) {
         heap->reserve = _zend_mm_alloc_int(heap, heap->reserve_size  ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
      }
This failed because reserve_size contains a very large number.

The corruption of "alloc_globals->mm_heap->reserve_size" happens in the function  _zend_mm_free_int.This function is called from "shutdown_executor" about line 327.
That is "zend_ptr_stack_destroy(&EG(arg_types_stack));"

In the function _zend_mm_free_int a local var mm_block is loaded with "mm_block = ZEND_MM_HEADER_OF(p);"
This header contains size=0,next=0 (hmm size=0 sounds wrong). 
The value in "alloc_globals->mm_heap->reserve_size" is corrupted later on at the line "*cache = (zend_mm_free_block*)mm_block;" (about line 1968). 
So I guess that "cache" contains a wrong pointer.



This is as far as I could debug php.
 [2009-05-21 00:46 UTC] jani@php.net
What MPM are you using in Apache? (and when you give feedback, change 
the status to 'Open'..)
 [2009-05-21 07:41 UTC] iddekingej at lycos dot com
It is the default apache2 for kubuntu 8.10: apache2 2.2.9/Prefork
 [2009-05-21 11:03 UTC] lbarnaud@php.net
Verified with gcc 4.3.3 with -O2 on 5.2 and 5.3. (./configure --disable-all)

Shorter reproduce script:

<?

function do_throw() {
	throw new Exception();
}

class aa 
{
	function check()
	{
	}

	function dosome()
	{
		$this->check(do_throw());
	}
}
$l_aa=new aa();

$l_aa->dosome();
?>

The following patch against 5.3 may help to see the problem:

Index: Zend/zend_ptr_stack.h
===================================================================
RCS file: /repository/ZendEngine2/zend_ptr_stack.h,v
retrieving revision 1.22.2.2.2.1.2.3
diff -u -p -r1.22.2.2.2.1.2.3 zend_ptr_stack.h
--- Zend/zend_ptr_stack.h	31 Dec 2008 11:15:32 -0000	1.22.2.2.2.1.2.3
+++ Zend/zend_ptr_stack.h	21 May 2009 10:56:26 -0000
@@ -107,6 +107,9 @@ static inline void zend_ptr_stack_push(z
 static inline void *zend_ptr_stack_pop(zend_ptr_stack *stack)
 {
 	stack->top--;
+	if (stack->top < 0) {
+		return *(void**)0;
+	}
 	return *(--stack->top_element);
 }


The following patch avoids the crash (don't know exactly why):

Index: Zend/zend_vm_def.h
===================================================================
RCS file: /repository/ZendEngine2/zend_vm_def.h,v
retrieving revision 1.59.2.29.2.48.2.90
diff -u -p -r1.59.2.29.2.48.2.90 zend_vm_def.h
--- Zend/zend_vm_def.h	8 Apr 2009 13:19:34 -0000	1.59.2.29.2.48.2.90
+++ Zend/zend_vm_def.h	21 May 2009 11:01:28 -0000
@@ -4296,7 +4296,8 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTI
 			zval_ptr_dtor(&EX(object));
 		}
 		EX(called_scope) = DECODE_CTOR(EX(called_scope));
-		zend_ptr_stack_2_pop(&EG(arg_types_stack), (void**)&EX(object), (void**)&EX(fbc));
+		EX(object) = zend_ptr_stack_pop(&EG(arg_types_stack));
+		EX(fbc) = zend_ptr_stack_pop(&EG(arg_types_stack));
 	}
 
 	for (i=0; i<EX(op_array)->last_brk_cont; i++) {
 [2009-05-21 21:17 UTC] iddekingej at lycos dot com
I have some more information about this bug:

THis bug happens in the following situation:

$l_a->someMethod(other_fy())

When in "other_fy()" a exception is raised this bug occurs.

This bug doesn't happen when calling a normal function 

e.g.
someMethod(other_fy())


This bug happens in apache as module and in the CLI. (only in the cli there is no visible clue that something did go wrong).


In the function ZEND_HANDLE_EXCEPTION_SPEC_HANDLER (zend_vm_execute.h). 
I placed some debug output (EX(fbc)->common.function_name and EG(arg_types_stack).top)
before:

while (EX(fbc)) {
      EX(called_scope) = (zend_class_entry*)zend_ptr_stack_pop(&EG(arg_types_stack));
      if (EX(object)) {

and after

            zend_object_store_ctor_failed(EX(object) TSRMLS_CC);
            }
         }
         zval_ptr_dtor(&EX(object));
      }

After the exception is raised this function is called. 
The first time it is called, the variable fbc=NULL and arg_types_stack.top =3. Because 
EX(fbc)=NULL the while loop is skipped.

When this function is called the second time and fbc is not null(Contains data from the method "check") , 
and arg_type_stack.top is still 3. After the while loop arg_type_stack.top=-3, which is afcourse wrong . Because of this 
some memory corruption occurs.

So  maybe when calling a method and a expception is raised when the parameters are calculated the variable "fbc" is not set correctly 
or there is a missing "zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));"
 [2009-05-27 19:24 UTC] jani@php.net
See also bug #48408
 [2009-05-27 21:14 UTC] iddekingej at lycos dot com
I can confirm that this bug is probably caused by a compiler bug as mentioned in bug #48408.

When I compiled PHp with 4.1 and run the test script I didn't see the 
"(tried to allocate 140498868988960 bytes)" message.

I also added the debug output as described at [21 May 9:17pm UTC] and the "arg_type_stack.top=-3" bug didn't happen.
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Fri Apr 18 15:02:26 2014 UTC