From 42ede5597e820357685dcefd8c7d9a576a258bf1 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 2 May 2024 21:11:29 +0200 Subject: [PATCH] Fix persisting of inherited class constants Class constants are inherited to user classes without cloning. Thus, internal class constants should not be persisted at all. Simply keep pointing to the internal class constant. Fixes GH-14109 Closes GH-14114 --- NEWS | 4 ++++ ext/opcache/zend_persist.c | 7 ++++++- ext/opcache/zend_persist_calc.c | 6 ++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 92d93bed27f..dedf9db8e2e 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,10 @@ PHP NEWS . Fix crash when calling childNodes next() when iterator is exhausted. (nielsdos) +- Opcache: + . Fixed bug GH-14109 (Fix accidental persisting of internal class constant in + shm). (ilutov) + - XML: . Fixed bug GH-14124 (Segmentation fault with XML extension under certain memory limit). (nielsdos) diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 87f1aee1480..990ad64ed99 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -802,12 +802,17 @@ static zend_property_info *zend_persist_property_info(zend_property_info *prop) static void zend_persist_class_constant(zval *zv) { - zend_class_constant *c = zend_shared_alloc_get_xlat_entry(Z_PTR_P(zv)); + zend_class_constant *orig_c = Z_PTR_P(zv); + zend_class_constant *c = zend_shared_alloc_get_xlat_entry(orig_c); zend_class_entry *ce; if (c) { Z_PTR_P(zv) = c; return; + } else if (((orig_c->ce->ce_flags & ZEND_ACC_IMMUTABLE) && !(Z_CONSTANT_FLAGS(orig_c->value) & CONST_OWNED)) + || orig_c->ce->type == ZEND_INTERNAL_CLASS) { + /* Class constant comes from a different file in shm or internal class, keep existing pointer. */ + return; } else if (!ZCG(current_persistent_script)->corrupted && zend_accel_in_shm(Z_PTR_P(zv))) { return; diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index 4e3af0d68c6..abe0a280d9a 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -26,6 +26,7 @@ #include "zend_shared_alloc.h" #include "zend_operators.h" #include "zend_attributes.h" +#include "zend_constants.h" #define ADD_DUP_SIZE(m,s) ZCG(current_persistent_script)->size += zend_shared_memdup_size((void*)m, s) #define ADD_SIZE(m) ZCG(current_persistent_script)->size += ZEND_ALIGNED_SIZE(m) @@ -386,6 +387,11 @@ static void zend_persist_class_constant_calc(zval *zv) zend_class_constant *c = Z_PTR_P(zv); if (!zend_shared_alloc_get_xlat_entry(c)) { + if (((c->ce->ce_flags & ZEND_ACC_IMMUTABLE) && !(Z_CONSTANT_FLAGS(c->value) & CONST_OWNED)) + || c->ce->type == ZEND_INTERNAL_CLASS) { + /* Class constant comes from a different file in shm or internal class, keep existing pointer. */ + return; + } if (!ZCG(current_persistent_script)->corrupted && zend_accel_in_shm(Z_PTR_P(zv))) { return;