|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #65000 use after free (double free) caused by emalloc in _zval_copy_ctor_func
Submitted: 2013-06-09 16:05 UTC Modified: 2020-03-10 08:44 UTC
From: Assigned: cmb (profile)
Status: Closed Package: Reproducible crash
PHP Version: 5.4.16 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.
Block user comment
Status: Assign to:
Bug Type:
New email:
PHP Version: OS:


 [2013-06-09 16:05 UTC]
$ ./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: 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:

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

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


Expected result:
no crash

Actual result:


Add a Patch

Pull Requests

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2013-06-10 18:54 UTC]
-Type: Security +Type: Bug -Package: *General Issues +Package: Reproducible crash
 [2013-06-11 12:50 UTC]
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
  case IS_STRING:
+    ZVAL_NULL(zvalue);
  if (!IS_INTERNED(zvalue->value.str.val)) {
  zvalue->value.str.val = (char *) estrndup_rel(zvalue->value.str.val,
+ Z_TYPE_P(zvalue) = IS_STRING;

 but it definitly will brings performance slow down...
 [2013-06-11 14:28 UTC]
-Type: Bug +Type: Security -Private report: No +Private report: Yes
 [2013-06-11 14:29 UTC]
-Type: Security +Type: Bug
 [2013-06-28 06:59 UTC]
Are you going to commit this patch?
 [2020-03-10 08:44 UTC]
-Status: Open +Status: Closed -Assigned To: +Assigned To: cmb
 [2020-03-10 08:44 UTC]
> in case when emalloc […] fails

I assume this issue is resolved, since ZendMM is infallible.
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Wed Aug 05 18:23:06 2020 UTC