Skip to content

Commit 8248810

Browse files
committed
Fix default_object_handlers pointing to invalid memory with file_cache
1 parent c0f5d46 commit 8248810

File tree

3 files changed

+22
-6
lines changed

3 files changed

+22
-6
lines changed

Zend/zend_enum.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@
3434

3535
ZEND_API zend_class_entry *zend_ce_unit_enum;
3636
ZEND_API zend_class_entry *zend_ce_backed_enum;
37-
38-
static zend_object_handlers enum_handlers;
37+
ZEND_API zend_object_handlers zend_enum_object_handlers;
3938

4039
zend_object *zend_enum_new(zval *result, zend_class_entry *ce, zend_string *case_name, zval *backing_value_zv)
4140
{
@@ -157,9 +156,9 @@ void zend_register_enum_ce(void)
157156
zend_ce_backed_enum = register_class_BackedEnum(zend_ce_unit_enum);
158157
zend_ce_backed_enum->interface_gets_implemented = zend_implement_backed_enum;
159158

160-
memcpy(&enum_handlers, &std_object_handlers, sizeof(zend_object_handlers));
161-
enum_handlers.clone_obj = NULL;
162-
enum_handlers.compare = zend_objects_not_comparable;
159+
memcpy(&zend_enum_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
160+
zend_enum_object_handlers.clone_obj = NULL;
161+
zend_enum_object_handlers.compare = zend_objects_not_comparable;
163162
}
164163

165164
void zend_enum_add_interfaces(zend_class_entry *ce)
@@ -183,7 +182,7 @@ void zend_enum_add_interfaces(zend_class_entry *ce)
183182
ce->interface_names[num_interfaces_before + 1].lc_name = zend_string_init("backedenum", sizeof("backedenum") - 1, 0);
184183
}
185184

186-
ce->default_object_handlers = &enum_handlers;
185+
ce->default_object_handlers = &zend_enum_object_handlers;
187186
}
188187

189188
zend_result zend_enum_build_backed_enum_table(zend_class_entry *ce)

Zend/zend_enum.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ BEGIN_EXTERN_C()
2626

2727
extern ZEND_API zend_class_entry *zend_ce_unit_enum;
2828
extern ZEND_API zend_class_entry *zend_ce_backed_enum;
29+
extern ZEND_API zend_object_handlers zend_enum_object_handlers;
2930

3031
void zend_register_enum_ce(void);
3132
void zend_enum_add_interfaces(zend_class_entry *ce);

ext/opcache/zend_file_cache.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "zend_interfaces.h"
2424
#include "zend_attributes.h"
2525
#include "zend_system_id.h"
26+
#include "zend_enum.h"
2627

2728
#include "php.h"
2829
#ifdef ZEND_WIN32
@@ -1714,6 +1715,21 @@ static void zend_file_cache_unserialize_class(zval *zv,
17141715
ZEND_MAP_PTR_INIT(ce->mutable_data, NULL);
17151716
ZEND_MAP_PTR_INIT(ce->static_members_table, NULL);
17161717
}
1718+
1719+
// Memory addresses of object handlers are not stable. They can change due to ASLR or order of linking dynamic. To
1720+
// avoid pointing to invalid memory we relink default_object_handlers with the first internal class in the class
1721+
// hierarchy, or pick the appropriate default handler if there is no internal parent class.
1722+
const zend_object_handlers *default_object_handlers = ce->ce_flags & ZEND_ACC_ENUM ? &zend_enum_object_handlers : &std_object_handlers;
1723+
zend_class_entry *parent = ce->parent;
1724+
if (parent && (ce->ce_flags & ZEND_ACC_LINKED)) {
1725+
while (parent && parent->type != ZEND_INTERNAL_CLASS) {
1726+
parent = parent->parent;
1727+
}
1728+
if (parent) {
1729+
default_object_handlers = parent->default_object_handlers;
1730+
}
1731+
}
1732+
ce->default_object_handlers = default_object_handlers;
17171733
}
17181734

17191735
static void zend_file_cache_unserialize_warnings(zend_persistent_script *script, void *buf)

0 commit comments

Comments
 (0)