Edit report at https://bugs.php.net/bug.php?id=65000&edit=1

 ID:                 65000
 Updated by:         larue...@php.net
 Reported by:        s...@php.net
 Summary:            use after free (double free) caused by emalloc in
                     _zval_copy_ctor_func
 Status:             Open
 Type:               Bug
 Package:            Reproducible crash
 Operating System:   Linux
 PHP Version:        5.4.16
 Block user comment: N
 Private report:     Y

 New Comment:

here is the replay I wrote to security, just for the record:
   A fix could be, set the zval type to be NULL, then doing the
estrndup, then set it back to IS_STRING:

@@ -118,10 +118,12 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue
ZEND_FILE_LINE_DC)
  break;
  case IS_CONSTANT:
  case IS_STRING:
+    ZVAL_NULL(zvalue);
  CHECK_ZVAL_STRING_REL(zvalue);
  if (!IS_INTERNED(zvalue->value.str.val)) {
  zvalue->value.str.val = (char *) estrndup_rel(zvalue->value.str.val,
zvalue->value.str.l
en);
  }
+ Z_TYPE_P(zvalue) = IS_STRING;
  break;


 but it definitly will brings performance slow down...


Previous Comments:
------------------------------------------------------------------------
[2013-06-09 16:05:18] s...@php.net

Description:
------------
$ ./php --version
PHP 5.4.16 (cli) (built: Jun  9 2013 17:56:24) (DEBUG)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologies
---
(gdb) r ~shm/php1.php 
Starting program: /home/fuzzphp/php-5.4.16/sapi/cli/php ~shm/php1.php

Fatal error: Allowed memory size of 33554432 bytes exhausted at 
/home/fuzzphp/php-5.4.16/Zend/zend_vm_execute.h:27134 (tried to allocate 
30000001 bytes) in /home/shm/php1.php on line 11

Program received signal SIGSEGV, Segmentation fault.
0x00000000008ebc07 in _zval_dtor_func (zvalue=0x7ffff7fdb4d8, 
__zend_filename=0xeac8e8 "/home/fuzzphp/php-5.4.16/Zend/zend_execute_API.c", 
__zend_lineno=438)
    at /home/fuzzphp/php-5.4.16/Zend/zend_variables.c:35
35                              CHECK_ZVAL_STRING_REL(zvalue);
(gdb) bt
#0  0x00000000008ebc07 in _zval_dtor_func (zvalue=0x7ffff7fdb4d8, 
__zend_filename=0xeac8e8 "/home/fuzzphp/php-5.4.16/Zend/zend_execute_API.c", 
__zend_lineno=438)
    at /home/fuzzphp/php-5.4.16/Zend/zend_variables.c:35
#1  0x00000000008da584 in _zval_dtor (zvalue=0x7ffff7fdb4d8, 
__zend_filename=0xeac8e8 "/home/fuzzphp/php-5.4.16/Zend/zend_execute_API.c", 
__zend_lineno=438)
    at /home/fuzzphp/php-5.4.16/Zend/zend_variables.h:35
#2  0x00000000008db528 in _zval_ptr_dtor (zval_ptr=0x7ffff7fdcb00, 
__zend_filename=0xeae170 "/home/fuzzphp/php-5.4.16/Zend/zend_variables.c", 
__zend_lineno=182)
    at /home/fuzzphp/php-5.4.16/Zend/zend_execute_API.c:438
#3  0x00000000008ec0c1 in _zval_ptr_dtor_wrapper (zval_ptr=0x7ffff7fdcb00) at 
/home/fuzzphp/php-5.4.16/Zend/zend_variables.c:182
#4  0x000000000090046a in zend_hash_apply_deleter (ht=0x116ad88, 
p=0x7ffff7fdcae8) at /home/fuzzphp/php-5.4.16/Zend/zend_hash.c:650
#5  0x00000000009005fb in zend_hash_graceful_reverse_destroy (ht=0x116ad88) at 
/home/fuzzphp/php-5.4.16/Zend/zend_hash.c:687
#6  0x00000000008daed3 in shutdown_executor () at 
/home/fuzzphp/php-5.4.16/Zend/zend_execute_API.c:247
#7  0x00000000008edf1e in zend_deactivate () at 
/home/fuzzphp/php-5.4.16/Zend/zend.c:938
#8  0x000000000086438f in php_request_shutdown (dummy=0x0) at 
/home/fuzzphp/php-5.4.16/main/main.c:1800
#9  0x0000000000990d12 in do_cli (argc=2, argv=0x7fffffffe628) at 
/home/fuzzphp/php-5.4.16/sapi/cli/php_cli.c:1171
#10 0x0000000000991418 in main (argc=2, argv=0x7fffffffe628) at 
/home/fuzzphp/php-5.4.16/sapi/cli/php_cli.c:1364
-----

It seems that _zval_copy_ctor_func can be used to trigger double free/use after 
free issue, in case when emalloc pointed here: 
http://lxr.php.net/xref/PHP_5_4/Zend/zend_variables.c#123 fails (estrndup calls 
emalloc internally). The interpreter runs destroy functions on error (memory 
exhastion) which lead to use value.str.val two times. Please see the test 
script for details.

I'm not sure how to fix the issue, so I left it for smarter than me. :-)


Test script:
---------------
<?php

ini_set('memory_limit', '32M');
$var5 = str_repeat("A",30000000);
$x = array($var5);

function crash_me(&$x) {
 die('failed :-(');
}

crash_me($var5);


Expected result:
----------------
no crash

Actual result:
--------------
SEGFAULT


------------------------------------------------------------------------



-- 
Edit this bug report at https://bugs.php.net/bug.php?id=65000&edit=1

Reply via email to