@@ -1055,25 +1055,64 @@ int ClassImpl::hasProperty(zval *object, zval *name, int has_set_exists, const z
1055
1055
ClassImpl *impl = self (entry);
1056
1056
ClassBase *meta = impl->_base ;
1057
1057
1058
- // convert the name to a Value object
1059
- Value key (name);
1060
-
1061
- // check if this is a callback property
1062
- if (impl->_properties .find (key) != impl->_properties .end ()) return true ;
1063
-
1064
- // call the C++ object
1065
- if (!meta->callIsset (base, key)) return false ;
1066
-
1067
- // property exists, but what does the user want to know
1068
- if (has_set_exists == 2 ) return true ;
1069
-
1070
- // we have to retrieve the property
1071
- Value value = meta->callGet (base, key);
1072
-
1073
- // should we check on NULL?
1074
- switch (has_set_exists) {
1075
- case 0 : return value.type () != Type::Null;
1076
- default : return value.boolValue ();
1058
+ // Watch out: the Zend engine is doing weird stuff here, the "name" parameter
1059
+ // that is passed to this method does not always have the "refcount" member
1060
+ // initialized (especially not when the call comes from property_exists()),
1061
+ // which makes it impossible to call Value{name} to convert name to a Php::Value
1062
+ if (Z_TYPE_P (name) == IS_STRING)
1063
+ {
1064
+ // we need a std::string for the lookup in the std::map
1065
+ std::string property (Z_STRVAL_P (name), Z_STRLEN_P (name));
1066
+
1067
+ // check if this is a callback property
1068
+ if (impl->_properties .find (property) != impl->_properties .end ()) return true ;
1069
+
1070
+ // we need the to pass a Php::Value to pass to the __isset() and _get() methods
1071
+ Value propvalue (property);
1072
+
1073
+ // call the C++ object
1074
+ if (!meta->callIsset (base, propvalue)) return false ;
1075
+
1076
+ // property exists, but what does the user want to know
1077
+ if (has_set_exists == 2 ) return true ;
1078
+
1079
+ // we have to retrieve the property
1080
+ Value value = meta->callGet (base, propvalue);
1081
+
1082
+ // should we check on NULL?
1083
+ switch (has_set_exists) {
1084
+ case 0 : return value.type () != Type::Null;
1085
+ default : return value.boolValue ();
1086
+ }
1087
+ }
1088
+ else
1089
+ {
1090
+ // the passed parameter was not a string, which is odd, but there could be a
1091
+ // scenario where the method is called with an object and the caller expect us
1092
+ // to convert the object back to a string (does this happen!?). Anyway: the call
1093
+ // does certainly not come from the property_exists() function because that function
1094
+ // already forces the param to be a string, and since the call does not come from
1095
+ // property_exists(), we also do not have to be extra careful in converting
1096
+ // the name into a Value object and can do that right now:
1097
+ Value property (name);
1098
+
1099
+ // check if this is a callback property
1100
+ if (impl->_properties .find (property) != impl->_properties .end ()) return true ;
1101
+
1102
+ // call the C++ object
1103
+ if (!meta->callIsset (base, property)) return false ;
1104
+
1105
+ // property exists, but what does the user want to know
1106
+ if (has_set_exists == 2 ) return true ;
1107
+
1108
+ // we have to retrieve the property
1109
+ Value value = meta->callGet (base, property);
1110
+
1111
+ // should we check on NULL?
1112
+ switch (has_set_exists) {
1113
+ case 0 : return value.type () != Type::Null;
1114
+ default : return value.boolValue ();
1115
+ }
1077
1116
}
1078
1117
}
1079
1118
catch (const NotImplemented &exception )
0 commit comments