Skip to content

Commit 2ccb314

Browse files
committed
fix #91 (private property in base class)
1 parent e241d1a commit 2ccb314

File tree

1 file changed

+61
-29
lines changed

1 file changed

+61
-29
lines changed

msgpack_unpack.c

Lines changed: 61 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,59 @@ static void msgpack_stack_pop(msgpack_unserialize_data_t *var_hashx, zval *v) /*
197197
}
198198
/* }}} */
199199

200+
static inline zval *update_property(const zend_class_entry *ce, HashTable *props, zend_string *mangled, zval *val) {
201+
const char *class_name, *prop_name;
202+
size_t prop_len;
203+
zval *new_val;
204+
zend_string *unmangled, *new_key;
205+
zend_property_info *existing_propinfo;
206+
207+
if (SUCCESS != zend_unmangle_property_name_ex(mangled, &class_name, &prop_name, &prop_len)) {
208+
return NULL;
209+
}
210+
211+
unmangled = zend_string_init(prop_name, prop_len, 0);
212+
existing_propinfo = zend_hash_find_ptr(&ce->properties_info, unmangled);
213+
214+
if ((class_name == NULL || !strcmp(class_name, "*") || !strcasecmp(class_name, ZSTR_VAL(ce->name)))
215+
&& (existing_propinfo != NULL)
216+
&& (existing_propinfo->flags & ZEND_ACC_PPP_MASK)) {
217+
if (existing_propinfo->flags & ZEND_ACC_PROTECTED) {
218+
new_key = zend_mangle_property_name(
219+
"*", 1, ZSTR_VAL(unmangled), ZSTR_LEN(unmangled), 0);
220+
} else if (existing_propinfo->flags & ZEND_ACC_PRIVATE) {
221+
if (class_name != NULL && strcmp(class_name, "*") != 0) {
222+
new_key = zend_mangle_property_name(
223+
class_name, strlen(class_name),
224+
ZSTR_VAL(unmangled), ZSTR_LEN(unmangled),
225+
0);
226+
} else {
227+
new_key = zend_mangle_property_name(
228+
ZSTR_VAL(existing_propinfo->ce->name), ZSTR_LEN(existing_propinfo->ce->name),
229+
ZSTR_VAL(unmangled), ZSTR_LEN(unmangled),
230+
0);
231+
}
232+
} else {
233+
ZEND_ASSERT(existing_propinfo->flags & ZEND_ACC_PUBLIC);
234+
new_key = unmangled;
235+
}
236+
} else {
237+
new_key = mangled;
238+
}
239+
240+
Z_TRY_ADDREF_P(val);
241+
new_val = zend_hash_update_ind(props, new_key, val);
242+
243+
if (new_key != unmangled) {
244+
zend_string_release(unmangled);
245+
}
246+
if (new_key != mangled) {
247+
zend_string_release(new_key);
248+
}
249+
250+
return new_val;
251+
}
252+
200253
static zend_class_entry* msgpack_unserialize_class(zval **container, zend_string *class_name, zend_bool init_class) /* {{{ */ {
201254
zend_class_entry *ce;
202255
int func_call_status;
@@ -260,22 +313,12 @@ static zend_class_entry* msgpack_unserialize_class(zval **container, zend_string
260313
object_init_ex(container_val, ce);
261314

262315
if (Z_TYPE(container_tmp) != IS_UNDEF) {
263-
ZEND_HASH_FOREACH_STR_KEY_VAL(HASH_OF(&container_tmp), str_key, val) {
264-
const char *class_name, *prop_name;
265-
size_t prop_len;
266-
zend_class_entry *ce;
267-
zend_function *__set, *__get;
268-
269-
if (!str_key) {
270-
continue;
271-
}
272-
ce = Z_OBJCE_P(container_val);
273-
UNSET_MAGIC_METHODS(ce);
274-
zend_unmangle_property_name_ex(str_key, &class_name, &prop_name, &prop_len);
275-
zend_update_property(ce, container_val, prop_name, prop_len, val);
276-
RESET_MAGIC_METHODS(ce);
277-
278-
} ZEND_HASH_FOREACH_END();
316+
HashTable *props = Z_OBJPROP_P(container_val);
317+
ZEND_HASH_FOREACH_STR_KEY_VAL(HASH_OF(&container_tmp), str_key, val)
318+
{
319+
update_property(ce, props, str_key, val);
320+
}
321+
ZEND_HASH_FOREACH_END();
279322
zval_dtor(&container_tmp);
280323
}
281324

@@ -491,7 +534,7 @@ int msgpack_unserialize_array_item(msgpack_unserialize_data *unpack, zval **cont
491534
zval *nval;
492535

493536
if (!*container || Z_TYPE_P(*container) != IS_ARRAY) {
494-
return -1;
537+
return -1;
495538
}
496539

497540
nval = zend_hash_next_index_insert(Z_ARRVAL_P(*container), obj);
@@ -649,18 +692,7 @@ int msgpack_unserialize_map_item(msgpack_unserialize_data *unpack, zval **contai
649692
break;
650693
case IS_STRING:
651694
if (Z_OBJCE_P(container_val) != PHP_IC_ENTRY) {
652-
const char *class_name, *prop_name;
653-
zend_class_entry *ce = Z_OBJCE_P(container_val);
654-
zval rv;
655-
size_t prop_len;
656-
zend_function *__get, *__set;
657-
658-
UNSET_MAGIC_METHODS(ce);
659-
zend_unmangle_property_name_ex(Z_STR_P(key), &class_name, &prop_name, &prop_len);
660-
zend_update_property(ce, container_val, prop_name, prop_len, val);
661-
nval = zend_read_property(Z_OBJCE_P(container_val), container_val, prop_name, prop_len, 1, &rv);
662-
RESET_MAGIC_METHODS(ce);
663-
695+
nval = update_property(Z_OBJCE_P(container_val), Z_OBJPROP_P(container_val), Z_STR_P(key), val);
664696
zval_ptr_dtor(key);
665697
zval_ptr_dtor(val);
666698
} else {

0 commit comments

Comments
 (0)