Skip to content

Commit 7becfbf

Browse files
committed
Barely-tested support for property hooks on copied classes
1 parent 5b20bac commit 7becfbf

File tree

1 file changed

+71
-25
lines changed

1 file changed

+71
-25
lines changed

src/prepare.c

+71-25
Original file line numberDiff line numberDiff line change
@@ -182,40 +182,80 @@ static void prepare_class_function_table(const pmmpthread_ident_t* source, zend_
182182
} ZEND_HASH_FOREACH_END();
183183
} /* }}} */
184184

185-
/* {{{ */
186-
static void prepare_class_property_table(const pmmpthread_ident_t* source, zend_class_entry *candidate, zend_class_entry *prepared) {
185+
static zend_property_info* copy_property_info(
186+
const pmmpthread_ident_t* source,
187+
const zend_class_entry *candidate,
188+
zend_class_entry *prepared,
189+
const zend_property_info* info
190+
) {
191+
zend_property_info* dup = zend_hash_index_find_ptr(&PMMPTHREAD_ZG(resolve), (zend_ulong)info);
192+
if (dup) {
193+
return dup;
194+
}
187195

188-
zend_property_info *info;
189-
zend_string *name;
190-
ZEND_HASH_FOREACH_STR_KEY_PTR(&candidate->properties_info, name, info) {
191-
zend_property_info *dup;
196+
if (info->ce->type == ZEND_INTERNAL_CLASS) {
197+
dup = pemalloc(sizeof(zend_property_info), 1);
198+
}
199+
else {
200+
dup = zend_arena_alloc(&CG(arena), sizeof(zend_property_info));
201+
}
202+
memcpy(dup, info, sizeof(zend_property_info));
192203

193-
if (info->ce->type == ZEND_INTERNAL_CLASS) {
194-
dup = pemalloc(sizeof(zend_property_info), 1);
195-
} else {
196-
dup = zend_arena_alloc(&CG(arena), sizeof(zend_property_info));
197-
}
198-
memcpy(dup, info, sizeof(zend_property_info));
204+
zend_hash_index_update_ptr(&PMMPTHREAD_ZG(resolve), (zend_ulong)info, dup);
199205

200-
dup->name = pmmpthread_copy_string(info->name);
201-
if (info->doc_comment) {
202-
if (PMMPTHREAD_ZG(options) & PMMPTHREAD_INHERIT_COMMENTS) {
203-
dup->doc_comment = pmmpthread_copy_string(info->doc_comment);
204-
} else dup->doc_comment = NULL;
206+
dup->name = pmmpthread_copy_string(info->name);
207+
if (info->doc_comment) {
208+
if (PMMPTHREAD_ZG(options) & PMMPTHREAD_INHERIT_COMMENTS) {
209+
dup->doc_comment = pmmpthread_copy_string(info->doc_comment);
205210
}
211+
else dup->doc_comment = NULL;
212+
}
206213

207-
if (info->ce) {
208-
if (info->ce == candidate) {
209-
dup->ce = prepared;
210-
} else dup->ce = pmmpthread_prepared_entry(source, info->ce);
214+
if (info->ce) {
215+
if (info->ce == candidate) {
216+
dup->ce = prepared;
211217
}
218+
else dup->ce = pmmpthread_prepared_entry(source, info->ce);
219+
}
220+
221+
pmmpthread_copy_zend_type(&info->type, &dup->type);
212222

213-
pmmpthread_copy_zend_type(&info->type, &dup->type);
223+
if (info->attributes) {
224+
dup->attributes = pmmpthread_copy_attributes(source, info->attributes, info->ce->type == ZEND_INTERNAL_CLASS ? NULL : info->ce->info.user.filename);
225+
}
214226

215-
if (info->attributes) {
216-
dup->attributes = pmmpthread_copy_attributes(source, info->attributes, info->ce->type == ZEND_INTERNAL_CLASS ? NULL : info->ce->info.user.filename);
227+
#if PHP_VERSION_ID >= 80400
228+
if (info->prototype) {
229+
dup->prototype = copy_property_info(source, candidate, prepared, info->prototype);
230+
} else dup->prototype = NULL;
231+
232+
if (info->hooks) {
233+
dup->hooks = zend_arena_alloc(&CG(arena), ZEND_PROPERTY_HOOK_STRUCT_SIZE);
234+
for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) {
235+
if (info->hooks[i]) {
236+
const zend_function* original_hook = info->hooks[i];
237+
zend_function* copy_hook = pmmpthread_copy_function(source, original_hook);
238+
239+
if (original_hook->type == ZEND_USER_FUNCTION) {
240+
ZEND_ASSERT(original_hook->op_array.prop_info);
241+
copy_hook->op_array.prop_info = copy_property_info(source, candidate, prepared, info->hooks[i]->op_array.prop_info);
242+
}
243+
244+
dup->hooks[i] = copy_hook;
245+
} else dup->hooks[i] = NULL;
217246
}
247+
} else dup->hooks = NULL;
248+
#endif
218249

250+
return dup;
251+
}
252+
/* {{{ */
253+
static void prepare_class_property_table(const pmmpthread_ident_t* source, zend_class_entry *candidate, zend_class_entry *prepared) {
254+
255+
zend_property_info *info;
256+
zend_string *name;
257+
ZEND_HASH_FOREACH_STR_KEY_PTR(&candidate->properties_info, name, info) {
258+
zend_property_info* dup = copy_property_info(source, candidate, prepared, info);
219259
if (!zend_hash_str_add_ptr(&prepared->properties_info, name->val, name->len, dup)) {
220260
if (dup->doc_comment)
221261
zend_string_release(dup->doc_comment);
@@ -257,7 +297,11 @@ static void prepare_class_property_table(const pmmpthread_ident_t* source, zend_
257297
}
258298

259299
ZEND_HASH_FOREACH_PTR(&prepared->properties_info, info) {
260-
if (info->ce == prepared && (info->flags & ZEND_ACC_STATIC) == 0) {
300+
if (info->ce == prepared && (info->flags & ZEND_ACC_STATIC) == 0
301+
#if PHP_VERSION_ID >= 80400
302+
&& (info->flags & ZEND_ACC_VIRTUAL) == 0
303+
#endif
304+
) {
261305
prepared->properties_info_table[OBJ_PROP_TO_NUM(info->offset)] = info;
262306
}
263307
} ZEND_HASH_FOREACH_END();
@@ -484,6 +528,8 @@ static zend_class_entry* pmmpthread_copy_entry(const pmmpthread_ident_t* source,
484528
(candidate->doc_comment)) {
485529
prepared->doc_comment = pmmpthread_copy_string(candidate->doc_comment);
486530
} else prepared->doc_comment = NULL;
531+
prepared->num_hooked_props = candidate->num_hooked_props;
532+
prepared->num_hooked_prop_variance_checks = candidate->num_hooked_prop_variance_checks;
487533
#else
488534
(candidate->info.user.doc_comment)) {
489535
prepared->info.user.doc_comment = pmmpthread_copy_string(candidate->info.user.doc_comment);

0 commit comments

Comments
 (0)