Skip to content

Commit 9e7c2e5

Browse files
committed
Merge branch 'PHP-5.3' into PHP-5.4
* PHP-5.3: fix bug #63462 (Magic methods called twice for unset protected properties)
2 parents b69fd9c + 33b104c commit 9e7c2e5

File tree

3 files changed

+87
-1
lines changed

3 files changed

+87
-1
lines changed

NEWS

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ PHP NEWS
1313
. Fixed bug #63893 (Poor efficiency of strtr() using array with keys of very
1414
different length). (Gustavo)
1515
. Fixed bug #63882 (zend_std_compare_objects crash on recursion). (Dmitry)
16+
. Fixed bug #63462 (Magic methods called twice for unset protected
17+
properties). (Stas)
1618
. Support BITMAPV5HEADER in getimagesize(). (AsamK, Lars)
1719

1820
- Date:
@@ -40,7 +42,7 @@ PHP NEWS
4042
. Fixed bug #63916 (PDO::PARAM_INT casts to 32bit int internally even
4143
on 64bit builds in pdo_sqlite). (srgoogleguy, Lars)
4244

43-
?? ??? 2012, PHP 5.4.11
45+
17 Jan 2012, PHP 5.4.11
4446

4547
- Core:
4648
. Fixed bug #63762 (Sigsegv when Exception::$trace is changed by user).

Zend/tests/bug63462.phpt

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
--TEST--
2+
Test script to verify that magic methods should be called only once when accessing an unset property.
3+
--CREDITS--
4+
Marco Pivetta <ocramius@gmail.com>
5+
--FILE--
6+
<?php
7+
class Test {
8+
public $publicProperty;
9+
protected $protectedProperty;
10+
private $privateProperty;
11+
12+
public function __construct() {
13+
unset(
14+
$this->publicProperty,
15+
$this->protectedProperty,
16+
$this->privateProperty
17+
);
18+
}
19+
20+
function __get($name) {
21+
echo '__get ' . $name . "\n";
22+
return $this->$name;
23+
}
24+
25+
function __set($name, $value) {
26+
echo '__set ' . $name . "\n";
27+
$this->$name = $value;
28+
}
29+
30+
function __isset($name) {
31+
echo '__isset ' . $name . "\n";
32+
return isset($this->$name);
33+
}
34+
}
35+
36+
$test = new Test();
37+
38+
$test->nonExisting;
39+
$test->publicProperty;
40+
$test->protectedProperty;
41+
$test->privateProperty;
42+
isset($test->nonExisting);
43+
isset($test->publicProperty);
44+
isset($test->protectedProperty);
45+
isset($test->privateProperty);
46+
$test->nonExisting = 'value';
47+
$test->publicProperty = 'value';
48+
$test->protectedProperty = 'value';
49+
$test->privateProperty = 'value';
50+
51+
?>
52+
53+
--EXPECTF--
54+
__get nonExisting
55+
56+
Notice: Undefined property: Test::$nonExisting in %s on line %d
57+
__get publicProperty
58+
59+
Notice: Undefined property: Test::$publicProperty in %s on line %d
60+
__get protectedProperty
61+
62+
Notice: Undefined property: Test::$protectedProperty in %s on line %d
63+
__get privateProperty
64+
65+
Notice: Undefined property: Test::$privateProperty in %s on line %d
66+
__isset nonExisting
67+
__isset publicProperty
68+
__isset protectedProperty
69+
__isset privateProperty
70+
__set nonExisting
71+
__set publicProperty
72+
__set protectedProperty
73+
__set privateProperty
74+

Zend/zend_object_handlers.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,16 @@ static int zend_get_property_guard(zend_object *zobj, zend_property_info *proper
393393
info.name = Z_STRVAL_P(member);
394394
info.name_length = Z_STRLEN_P(member);
395395
info.h = zend_get_hash_value(Z_STRVAL_P(member), Z_STRLEN_P(member) + 1);
396+
} else if(property_info->name[0] == '\0'){
397+
const char *class_name = NULL, *prop_name = NULL;
398+
zend_unmangle_property_name(property_info->name, property_info->name_length, &class_name, &prop_name);
399+
if(class_name) {
400+
/* use unmangled name for protected properties */
401+
info.name = prop_name;
402+
info.name_length = strlen(prop_name);
403+
info.h = zend_get_hash_value(info.name, info.name_length+1);
404+
property_info = &info;
405+
}
396406
}
397407
if (!zobj->guards) {
398408
ALLOC_HASHTABLE(zobj->guards);

0 commit comments

Comments
 (0)