php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #60498 Unset obj.prop. thru ArrayAccess while iterating thru ArrayIterator cause error
Submitted: 2011-12-12 12:28 UTC Modified: 2021-01-26 11:22 UTC
Votes:9
Avg. Score:4.6 ± 0.8
Reproduced:8 of 8 (100.0%)
Same Version:7 (87.5%)
Same OS:6 (75.0%)
From: michal dot brzuchalski at gmail dot com Assigned: nikic (profile)
Status: Closed Package: SPL related
PHP Version: 5.6 OS:
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please !
Your email address:
MUST BE VALID
Solve the problem:
1 + 35 = ?
Subscribe to this entry?

 
 [2011-12-12 12:28 UTC] michal dot brzuchalski at gmail dot com
Description:
------------
Using foreach to iterate object which implements IteratorAggregate and 
ArrayAccess while iterating with iterator created by ArrayIterator($this) causes 
error in internal spl_array_update_pos when trying to unset object property thru 
arrayaccess interface:

debug:

#0  0x0000000802f9cd2f in spl_array_update_pos (intern=0x80847d778) at 
/usr/ports/lang/php5/work/php-5.3.8/ext/spl/spl_array.c:101
101                     intern->pos_h = pos->h;
[New Thread 8016041c0 (LWP 100187/httpd)]
(gdb) bt
#0  0x0000000802f9cd2f in spl_array_update_pos (intern=0x80847d778) at 
/usr/ports/lang/php5/work/php-5.3.8/ext/spl/spl_array.c:101
#1  0x0000000802fa00aa in spl_array_next_no_verify (intern=0x80847d778, 
aht=0x8082764a8) at /usr/ports/lang/php5/work/php-5.3.8/ext/spl/spl_array.c:858
#2  0x0000000802fa0566 in spl_array_it_move_forward (iter=0x808428330) at 
/usr/ports/lang/php5/work/php-5.3.8/ext/spl/spl_array.c:983
#3  0x0000000803189a25 in ZEND_FE_FETCH_SPEC_VAR_HANDLER 
(execute_data=0x807a0a268) at zend_vm_execute.h:9014
#4  0x00000008031616aa in execute (op_array=0x803af3d00) at 
zend_vm_execute.h:107
#5  0x000000080311c307 in zend_call_function (fci=0x7fffffffcc50, 
fci_cache=0x7fffffffcc20) at /usr/ports/lang/php5/work/php-
5.3.8/Zend/zend_execute_API.c:968
#6  0x0000000802fcd3ee in zif_call_user_func (ht=2, return_value=0x8082bd5d0, 
return_value_ptr=0x0, this_ptr=0x0, return_value_used=1) at 
/usr/ports/lang/php5/work/php-5.3.8/ext/standard/basic_functions.c:4772
#7  0x000000080316271c in zend_do_fcall_common_helper_SPEC 
(execute_data=0x807a09c48) at zend_vm_execute.h:320
#8  0x00000008031636c5 in ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER 
(execute_data=0x807a09c48) at zend_vm_execute.h:425
#9  0x00000008031616aa in execute (op_array=0x807af1c50) at 
zend_vm_execute.h:107
#10 0x000000080312de5d in zend_execute_scripts (type=8, retval=0x0, 
file_count=3) at /usr/ports/lang/php5/work/php-5.3.8/Zend/zend.c:1236
#11 0x00000008030ad482 in php_execute_script (primary_file=0x7fffffffe5a0) at 
/usr/ports/lang/php5/work/php-5.3.8/main/main.c:2284
#12 0x0000000803221e45 in php_handler (r=0x803ba40a0) at 
/usr/ports/lang/php5/work/php-5.3.8/sapi/apache2handler/sapi_apache2.c:669
#13 0x000000000043dd1a in ap_run_handler (r=0x803ba40a0) at config.c:157
#14 0x000000000043e643 in ap_invoke_handler (r=0x803ba40a0) at config.c:376
#15 0x000000000044f9d4 in ap_process_request (r=0x803ba40a0) at 
http_request.c:282
#16 0x000000000044c7b4 in ap_process_http_connection (c=0x803afa290) at 
http_core.c:190
#17 0x00000000004475aa in ap_run_process_connection (c=0x803afa290) at 
connection.c:43
#18 0x0000000000447a2b in ap_process_connection (c=0x803afa290, csd=0x803afa0a0) 
at connection.c:190
#19 0x0000000000456d85 in child_main (child_num_arg=37) at prefork.c:667
#20 0x0000000000456f3c in make_child (s=0x80161c708, slot=37) at prefork.c:768
#21 0x0000000000457629 in ap_mpm_run (_pconf=0x801615028, plog=0x801647028, 
s=0x80161c708) at prefork.c:1068
#22 0x000000000042410b in main (argc=2, argv=0x7fffffffeb20) at main.c:739
(gdb) bt full


Test script:
---------------
class obj implements \ArrayAccess , \IteratorAggregate {

    public function __construct() {
        foreach(array("one" => 1, "two" => 2, "three" => 3) as $offset => $value) $this->{$offset} = $value;
    }
    public function offsetSet($offset, $value) {
        $this->{$offset} = $value;
    }
    public function offsetExists($offset) {
        return isset($this->{$offset});
    }
    public function offsetUnset($offset) {
        unset($this->{$offset});
    }
    public function offsetGet($offset) {
        return isset($this->{$offset}) ? $this->{$offset} : null;
    }
	function getIterator() {
	  	return new \ArrayIterator($this);
	}
}

$obj = new obj;

foreach($obj as $offset => $value) unset($obj[$offset]);

print_r($obj);

foreach(get_object_vars($obj) as $offset => $value) unset($obj[$offset]);

print_r($obj);


Expected result:
----------------
obj Object
(
)
obj Object
(
)

Actual result:
--------------
The first foreach cause an internal error second one is ok

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2011-12-12 13:04 UTC] michal dot brzuchalski at gmail dot com
-Operating System: Unix +Operating System: FreeBSD
 [2011-12-12 13:04 UTC] michal dot brzuchalski at gmail dot com
Sorry no Unix but FreeBSD
 [2016-03-20 12:59 UTC] nikic@php.net
-Status: Open +Status: Verified -Operating System: FreeBSD +Operating System: -PHP Version: 5.3.8 +PHP Version: 5.6
 [2016-03-20 12:59 UTC] nikic@php.net
This issue still exists in PHP 5.6. It does not exist in PHP 7.0.

Valgrind:

==9299== Invalid read of size 8
==9299==    at 0x8FC1A6: zend_hash_move_forward_ex (zend_hash.c:1047)
==9299==    by 0x700BFC: spl_array_next_no_verify (spl_array.c:965)
==9299==    by 0x701009: spl_array_it_move_forward (spl_array.c:1079)
==9299==    by 0x94CB3A: ZEND_FE_FETCH_SPEC_VAR_HANDLER (zend_vm_execute.h:14027)
==9299==    by 0x92D8F5: execute_ex (zend_vm_execute.h:363)
==9299==    by 0x92D97E: zend_execute (zend_vm_execute.h:388)
==9299==    by 0x8E8CF3: zend_execute_scripts (zend.c:1341)
==9299==    by 0x84EED3: php_execute_script (main.c:2613)
==9299==    by 0x99D0C4: do_cli (php_cli.c:994)
==9299==    by 0x99E3F2: main (php_cli.c:1378)
==9299==  Address 0xbf77840 is 32 bytes inside a block of size 72 free'd
==9299==    at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9299==    by 0x8AEECA: _efree (zend_alloc.c:2437)
==9299==    by 0x8F9417: i_zend_hash_bucket_delete (zend_hash.c:187)
==9299==    by 0x8FAD3B: zend_hash_del_key_or_index (zend_hash.c:526)
==9299==    by 0x922CFB: zend_std_unset_property (zend_object_handlers.c:855)
==9299==    by 0x97CF42: ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER (zend_vm_execute.h:30346)
==9299==    by 0x92D8F5: execute_ex (zend_vm_execute.h:363)
==9299==    by 0x92D97E: zend_execute (zend_vm_execute.h:388)
==9299==    by 0x8D35A8: zend_call_function (zend_execute_API.c:829)
==9299==    by 0x909088: zend_call_method (zend_interfaces.c:97)
==9299==    by 0x923098: zend_std_unset_dimension (zend_object_handlers.c:897)
==9299==    by 0x99A355: ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER (zend_vm_execute.h:41212)
==9299==
 [2021-01-26 11:22 UTC] nikic@php.net
-Status: Verified +Status: Closed -Assigned To: +Assigned To: nikic
 [2021-01-26 11:22 UTC] nikic@php.net
Per above comment, the crash was fixed in PHP 7.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 23:01:26 2024 UTC