php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #34467 foreach + __get + __set incosistency
Submitted: 2005-09-11 22:27 UTC Modified: 2005-10-10 11:51 UTC
From: stochnagara at hotmail dot com Assigned: dmitry
Status: Closed Package: Class/Object related
PHP Version: 5CVS-2005-09-11 OS: *
Private report: No CVE-ID:
 [2005-09-11 22:27 UTC] stochnagara at hotmail dot com
Description:
------------
There is some incostistency with foreach and a class which has __get and __set methods. I don't know what is the intended behaviour but there is a problem there when assigning a foreach key or value to an overloaded member of such class.

See comments in the expected result region.

Reproduce code:
---------------
<? class abc {
	function __set ($key, $value) { echo "__set ($key,$value)<br/>"; $this->arr[$key] = $value; }
	function /*&*/ __get ($key) { echo "__get ($key)<br/>"; return $this->arr[$key]; } 
	function __isset ($key) { echo "__isset ($key)<br/>"; return isset ($this->arr[$key]); }
	function __unset ($key) { echo "__unset ($key)<br/>"; unset ($this->arr[$key]); }
	private $arr;
}
$abc = new abc();
foreach (array (1,2,3) as $abc->k => $v) {
	print_r($abc);echo ';'; var_dump($abc->k);echo ';';
}
$abc->k = 4;
echo '-----<br/>';
foreach (array (1,2,3) as $abc->k => $v) {
	print_r($abc);echo ';'; var_dump($abc->k);echo ';';
}
echo '<br/>-----<br/>';
$abc_value = new abc();
foreach (array (1,2,3) as $v => $abc_value->k) {
	print_r($abc_value);echo ';'; var_dump($abc_value->k);echo ';';
}


Expected result:
----------------
Depends of specification.

Case 1 : First foreach fills $arr with keys. Others are ok.
Case 2 : Second foreach does not fill $arr with keys.

Note 1! 
When __get is changed to return by reference, first foreach behaves exactly like the second one.

Note 2!
Third foreach calls __set while first and second do not.

Actual result:
--------------
__get (k)
abc Object ( [arr:private] => Array ( ) ) ;__get (k)
NULL ;__get (k)
abc Object ( [arr:private] => Array ( ) ) ;__get (k)
NULL ;__set (k,4)
-----
__get (k)
abc Object ( [arr:private] => Array ( [k] => 0 ) ) ;__get (k)
int(0) ;__get (k)
abc Object ( [arr:private] => Array ( [k] => 1 ) ) ;__get (k)
int(1) ;
-----
__set (k,1)
abc Object ( [arr:private] => Array ( [k] => 1 ) ) ;__get (k)
int(1) ;__set (k,2)
abc Object ( [arr:private] => Array ( [k] => 2 ) ) ;__get (k)
int(2) ;

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-09-12 00:33 UTC] sniper@php.net
Thank you for this bug report. To properly diagnose the problem, we
need a short but complete example script to be able to reproduce
this bug ourselves. 

A proper reproducing script starts with <?php and ends with ?>,
is max. 10-20 lines long and does not require any external 
resources such as databases, etc.

If possible, make the script source available online and provide
an URL to it here. Try to avoid embedding huge scripts into the report.


 [2005-09-12 10:13 UTC] stochnagara at hotmail dot com
This is the link to a zip containing all 6 test cases.

http://debian.fmi.uni-sofia.bg/~kapitancho/bug34667.zip

In tests 4, 5 and 6 function __get returns by reference while in 1, 2 and 3 does not.

Tests 1 and 4 show foreach behavoiur when the overloaded property used as key is not initialized.

Tests 2 and 5 show foreach behavoiur when the overloaded property used as key is initialized.

Tests 3 and 4 show foreach behavoiur when the overloaded property is used as value.

If you need more information I will provide it:)
 [2005-09-12 11:36 UTC] stochnagara at hotmail dot com
That's the shortest I can (run this sample with function & __get too).

<? 
class abc {
	function __set ($key, $value) { $this->arr[$key] = $value; }
	function __get ($key) { return $this->arr[$key]; } 
	private $arr;
}
$abc = new abc();
foreach (array (1,2,3) as $abc->k => $v) print_r($abc);
$abc->k = 4;
foreach (array (1,2,3) as $abc->k => $v) print_r($abc);
$abc_value = new abc();
foreach (array (1,2,3) as $v => $abc_value->k) print_r($abc_value);
?>
 [2005-09-12 13:27 UTC] sniper@php.net
Dmitry, check this out please. I get some leaks too with latest CVS. (PHP_5_1 branch)

 [2005-10-10 11:51 UTC] dmitry@php.net
Fixed in HEAD and PHP_5_1.
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Sun Apr 20 01:02:05 2014 UTC