php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #68896 Changing ArrayObject value cause Segment Fault
Submitted: 2015-01-24 04:53 UTC Modified: 2015-01-25 03:18 UTC
From: jrbasso at gmail dot com Assigned: laruence (profile)
Status: Closed Package: SPL related
PHP Version: master-Git-2015-01-24 (Git) 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.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: jrbasso at gmail dot com
New email:
PHP Version: OS:

 

 [2015-01-24 04:53 UTC] jrbasso at gmail dot com
Description:
------------
On PHP 7 (git master rev. be5337421680f059f7b23dd530645e070b15715a) when execute the code below it causes a segment fault.

You can also see the error on http://3v4l.org/lV2FT

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

$obj = new ArrayObject(["a" => 1]);
$obj["a"] .= "test";
var_dump($obj["a"]);

Expected result:
----------------
string(5) "1test"

Actual result:
--------------
$ ./sapi/cli/php -r '$obj = new ArrayObject(["a" => 1]); $obj["a"] .= "test"; var_dump($obj["a"]);'
php: /root/php-src-dbg/Zend/zend_hash.c:284: _zend_hash_add_or_update_i: Assertion `&p->val != pData' failed.
Aborted


(gdb) bt
#0  0x00007ffff61840d5 in raise () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x00007ffff618783b in abort () from /lib/x86_64-linux-gnu/libc.so.6
#2  0x00007ffff617cd9e in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#3  0x00007ffff617ce42 in __assert_fail () from /lib/x86_64-linux-gnu/libc.so.6
#4  0x00000000008f27d4 in _zend_hash_add_or_update_i (ht=0x7ffff48583c8, key=0x7ffff48579c0, pData=0x7ffff485e8c0, flag=5, __zend_filename=0xe0fe68 "/.../php-src-dbg/Zend/zend_hash.h",
    __zend_lineno=317) at /.../php-src-dbg/Zend/zend_hash.c:284
#5  0x00000000008f2b06 in _zend_hash_update_ind (ht=0x7ffff48583c8, key=0x7ffff48579c0, pData=0x7ffff485e8c0, __zend_filename=0xe0fe68 "/.../php-src-dbg/Zend/zend_hash.h", __zend_lineno=317)
    at /.../php-src-dbg/Zend/zend_hash.c:338
#6  0x0000000000778904 in zend_symtable_update_ind (ht=0x7ffff48583c8, key=0x7ffff48579c0, pData=0x7ffff485e8c0) at /.../php-src-dbg/Zend/zend_hash.h:317
#7  0x000000000077a27d in spl_array_write_dimension_ex (check_inherited=1, object=0x7ffff4813090, offset=0x7ffff48750d0, value=0x7ffff485e8c0) at /.../php-src-dbg/ext/spl/spl_array.c:493
#8  0x000000000077a3c2 in spl_array_write_dimension (object=0x7ffff4813090, offset=0x7ffff48750d0, value=0x7ffff485e8c0) at /.../php-src-dbg/ext/spl/spl_array.c:533
#9  0x000000000092cca8 in zend_binary_assign_op_obj_dim (object=0x7ffff4813090, property=0x7ffff48750d0, value=0x7ffff48750e0, retval=0x0, binary_op=0x8d8b83 <concat_function>)
    at /.../php-src-dbg/Zend/zend_execute.c:945
#10 0x0000000000968fda in zend_binary_assign_op_dim_helper_SPEC_CV_CONST (binary_op=0x8d8b83 <concat_function>, execute_data=0x7ffff4813030) at /.../php-src-dbg/Zend/zend_vm_execute.h:24794
#11 0x0000000000969879 in ZEND_ASSIGN_CONCAT_SPEC_CV_CONST_HANDLER (execute_data=0x7ffff4813030) at /.../php-src-dbg/Zend/zend_vm_execute.h:25018
#12 0x000000000092f72c in execute_ex (execute_data=0x7ffff4813030) at /.../php-src-dbg/Zend/zend_vm_execute.h:352
#13 0x000000000092f87e in zend_execute (op_array=0x7ffff4880000, return_value=0x7fffffffcf70) at /.../php-src-dbg/Zend/zend_vm_execute.h:381
#14 0x00000000008caf30 in zend_eval_stringl (str=0x11b2a10 "$obj = new ArrayObject([\"a\" => 1]); $obj[\"a\"] .= \"test\"; var_dump($obj[\"a\"]);", str_len=77, retval_ptr=0x0,
    string_name=0xe51e34 "Command line code") at /.../php-src-dbg/Zend/zend_execute_API.c:1074
#15 0x00000000008cb110 in zend_eval_stringl_ex (str=0x11b2a10 "$obj = new ArrayObject([\"a\" => 1]); $obj[\"a\"] .= \"test\"; var_dump($obj[\"a\"]);", str_len=77, retval_ptr=0x0,
    string_name=0xe51e34 "Command line code", handle_exceptions=1) at /.../php-src-dbg/Zend/zend_execute_API.c:1115
#16 0x00000000008cb1ab in zend_eval_string_ex (str=0x11b2a10 "$obj = new ArrayObject([\"a\" => 1]); $obj[\"a\"] .= \"test\"; var_dump($obj[\"a\"]);", retval_ptr=0x0,
    string_name=0xe51e34 "Command line code", handle_exceptions=1) at /.../php-src-dbg/Zend/zend_execute_API.c:1126
#17 0x0000000000985a8e in do_cli (argc=3, argv=0x11b2990) at /.../php-src-dbg/sapi/cli/php_cli.c:1022
#18 0x0000000000986ace in main (argc=3, argv=0x11b2990) at /.../php-src-dbg/sapi/cli/php_cli.c:1361

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-01-24 15:30 UTC] laruence@php.net
-Assigned To: +Assigned To: laruence
 [2015-01-24 15:31 UTC] laruence@php.net
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index c71c032..6bacfcd 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -939,14 +939,14 @@ static void zend_binary_assign_op_obj_dim(zval *object, zval *property, zval *va
 			}
 			ZVAL_COPY_VALUE(z, value);
 		}
-		ZVAL_DEREF(z);
-		SEPARATE_ZVAL_NOREF(z);
-		binary_op(z, z, value);
-		Z_OBJ_HT_P(object)->write_dimension(object, property, z);
+		ZVAL_COPY_VALUE(&rv, z);
+		SEPARATE_ZVAL_IF_NOT_REF(&rv);
+		binary_op(&rv, &rv, value);
+		Z_OBJ_HT_P(object)->write_dimension(object, property, &rv);
 		if (retval) {
-			ZVAL_COPY(retval, z);
+			ZVAL_COPY(retval, &rv);
 		}
-		zval_ptr_dtor(z);
+		zval_ptr_dtor(&rv);
 	} else {
 		zend_error(E_WARNING, "Attempt to assign property of non-object");
 		if (retval) {
 [2015-01-25 03:18 UTC] laruence@php.net
actually, if read_dim return a pointer which is not &rv, then seems it is unnecessary to call write_dim again.

like:

diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index c71c032..4fb3876 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -942,11 +942,13 @@ static void zend_binary_assign_op_obj_dim(zval *object, zval *property, zval *va
 		ZVAL_DEREF(z);
 		SEPARATE_ZVAL_NOREF(z);
 		binary_op(z, z, value);
-		Z_OBJ_HT_P(object)->write_dimension(object, property, z);
+		if (z == &rv) {
+			Z_OBJ_HT_P(object)->write_dimension(object, property, z);
+			zval_ptr_dtor(z);
+		}
 		if (retval) {
 			ZVAL_COPY(retval, z);
 		}
-		zval_ptr_dtor(z);
 	} else {
 		zend_error(E_WARNING, "Attempt to assign property of non-object");
 		if (retval) {

thanks
 [2015-01-26 08:25 UTC] dmitry@php.net
Automatic comment on behalf of dmitry@zend.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=371dc9b6a659399ede7d3c784f3c6ff800045ab2
Log: Fixed bug #68896 (Changing ArrayObject value cause Segment Fault)
 [2015-01-26 08:25 UTC] dmitry@php.net
-Status: Assigned +Status: Closed
 [2016-07-20 11:39 UTC] davey@php.net
Automatic comment on behalf of dmitry@zend.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=371dc9b6a659399ede7d3c784f3c6ff800045ab2
Log: Fixed bug #68896 (Changing ArrayObject value cause Segment Fault)
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Wed Oct 21 05:01:23 2020 UTC