From 89a371440107e4a007b2a4446259cfcd391bf5c6 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 22 Sep 2022 14:07:51 +0200 Subject: [PATCH] Fix default_object_handlers pointing to invalid memory with file_cache --- Zend/zend_enum.c | 11 +++++------ Zend/zend_enum.h | 1 + azure-pipelines.yml | 10 +++++----- ext/opcache/zend_file_cache.c | 5 +++++ 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/Zend/zend_enum.c b/Zend/zend_enum.c index 192d0eca99131..3e455b702cbf2 100644 --- a/Zend/zend_enum.c +++ b/Zend/zend_enum.c @@ -34,8 +34,7 @@ ZEND_API zend_class_entry *zend_ce_unit_enum; ZEND_API zend_class_entry *zend_ce_backed_enum; - -static zend_object_handlers enum_handlers; +ZEND_API zend_object_handlers zend_enum_object_handlers; zend_object *zend_enum_new(zval *result, zend_class_entry *ce, zend_string *case_name, zval *backing_value_zv) { @@ -157,9 +156,9 @@ void zend_register_enum_ce(void) zend_ce_backed_enum = register_class_BackedEnum(zend_ce_unit_enum); zend_ce_backed_enum->interface_gets_implemented = zend_implement_backed_enum; - memcpy(&enum_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - enum_handlers.clone_obj = NULL; - enum_handlers.compare = zend_objects_not_comparable; + memcpy(&zend_enum_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + zend_enum_object_handlers.clone_obj = NULL; + zend_enum_object_handlers.compare = zend_objects_not_comparable; } void zend_enum_add_interfaces(zend_class_entry *ce) @@ -183,7 +182,7 @@ void zend_enum_add_interfaces(zend_class_entry *ce) ce->interface_names[num_interfaces_before + 1].lc_name = zend_string_init("backedenum", sizeof("backedenum") - 1, 0); } - ce->default_object_handlers = &enum_handlers; + ce->default_object_handlers = &zend_enum_object_handlers; } zend_result zend_enum_build_backed_enum_table(zend_class_entry *ce) diff --git a/Zend/zend_enum.h b/Zend/zend_enum.h index 797eb0c8ab5b6..dbb230c4175c3 100644 --- a/Zend/zend_enum.h +++ b/Zend/zend_enum.h @@ -26,6 +26,7 @@ BEGIN_EXTERN_C() extern ZEND_API zend_class_entry *zend_ce_unit_enum; extern ZEND_API zend_class_entry *zend_ce_backed_enum; +extern ZEND_API zend_object_handlers zend_enum_object_handlers; void zend_register_enum_ce(void); void zend_enum_add_interfaces(zend_class_entry *ce); diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 2d9018ff67670..bc4625894a4ce 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -33,6 +33,11 @@ jobs: parameters: configurationName: I386_DEBUG_ZTS configurationParameters: '--enable-debug --enable-zts' + - template: azure/opcache_variation_job.yml + parameters: + configurationName: DEBUG_NTS_OPCACHE + configurationParameters: '--enable-debug --disable-zts' + timeoutInMinutes: 120 - ${{ if eq(variables['Build.Reason'], 'Schedule') }}: - template: azure/i386/job.yml parameters: @@ -59,11 +64,6 @@ jobs: --enable-debug --enable-zts --enable-address-sanitizer --enable-undefined-sanitizer CFLAGS='-fno-sanitize-recover' timeoutInMinutes: 90 - - template: azure/opcache_variation_job.yml - parameters: - configurationName: DEBUG_NTS_OPCACHE - configurationParameters: '--enable-debug --disable-zts' - timeoutInMinutes: 120 - template: azure/job.yml parameters: configurationName: DEBUG_NTS_REPEAT diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index a15736b72e5fe..1cd639403f68b 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -23,6 +23,7 @@ #include "zend_interfaces.h" #include "zend_attributes.h" #include "zend_system_id.h" +#include "zend_enum.h" #include "php.h" #ifdef ZEND_WIN32 @@ -1714,6 +1715,10 @@ static void zend_file_cache_unserialize_class(zval *zv, ZEND_MAP_PTR_INIT(ce->mutable_data, NULL); ZEND_MAP_PTR_INIT(ce->static_members_table, NULL); } + + // Memory addresses of object handlers are not stable. They can change due to ASLR or order of linking dynamic. To + // avoid pointing to invalid memory we relink default_object_handlers here. + ce->default_object_handlers = ce->ce_flags & ZEND_ACC_ENUM ? &zend_enum_object_handlers : &std_object_handlers; } static void zend_file_cache_unserialize_warnings(zend_persistent_script *script, void *buf)