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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
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

Pull Requests

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-2025 The PHP Group
All rights reserved.
Last updated: Sat May 03 08:01:28 2025 UTC