[PHP-CVS] [php-src] master: Zend: factor out guarded lazy-proxy forwarding in object handlers (#22983)

[email protected] (Weilin Du via GitHub) Mon, 3 Aug 2026 16:08:48 +0000
Newsgroups php.cvs
Message-ID <[email protected]>
Author: Weilin Du (LamentXU123)
Committer: GitHub (web-flow)
Pusher: LamentXU123
Date: 2026-08-04T00:08:45+08:00

Commit: https://github.com/php/php-src/commit/523a75eea9228ddd631eb64b8055456a68cf4c8c
Raw diff: https://github.com/php/php-src/commit/523a75eea9228ddd631eb64b8055456a68cf4c8c.diff

Zend: factor out guarded lazy-proxy forwarding in object handlers (#22983)

Refactor out duplicate logic to make the code looks more sensible.

Changed paths:
  M  Zend/zend_object_handlers.c


Diff:

diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index 313113d7dc28..754f603100c2 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -669,6 +669,23 @@ ZEND_API uint32_t *zend_get_recursion_guard(zend_object *zobj)
 	return &Z_GUARD_P(zv);
 }
 
+static zend_always_inline zend_object *zend_lazy_proxy_get_guarded_instance(
+		zend_object *zobj, zend_string *name, uint32_t guard_type)
+{
+	if (UNEXPECTED(zend_object_is_lazy_proxy(zobj)
+			&& zend_lazy_object_initialized(zobj))) {
+		zend_object *instance = zend_lazy_object_get_instance(zobj);
+		if (instance->ce->ce_flags & ZEND_ACC_USE_GUARDS) {
+			uint32_t *instance_guard = zend_get_property_guard(instance, name);
+			if ((*instance_guard) & guard_type) {
+				return instance;
+			}
+		}
+	}
+
+	return NULL;
+}
+
 ZEND_COLD static void zend_typed_property_uninitialized_access(const zend_property_info *prop_info, zend_string *name)
 {
 	zend_throw_error(NULL, "Typed property %s::$%s must not be accessed before initialization",
@@ -896,21 +913,16 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int
 	 * guard is already set for this property, we are inside a recursive
 	 * call from the real instance's __get/__isset. Forward directly to
 	 * the real instance to avoid double invocation. (GH-21478) */
-	if (UNEXPECTED(zend_object_is_lazy_proxy(zobj)
-			&& zend_lazy_object_initialized(zobj))) {
-		zend_object *instance = zend_lazy_object_get_instance(zobj);
-		if (instance->ce->ce_flags & ZEND_ACC_USE_GUARDS) {
-			uint32_t *instance_guard = zend_get_property_guard(instance, name);
-			uint32_t guard_type = ((type == BP_VAR_IS) && zobj->ce->__isset)
-				? IN_ISSET : IN_GET;
-			if ((*instance_guard) & guard_type) {
-				retval = zend_std_read_property(instance, name, type, cache_slot, rv);
-				if (retval == &EG(uninitialized_zval)) {
-					ZVAL_NULL(rv);
-					retval = rv;
-				}
-				return retval;
+	{
+		zend_object *instance = zend_lazy_proxy_get_guarded_instance(zobj, name,
+			((type == BP_VAR_IS) && zobj->ce->__isset) ? IN_ISSET : IN_GET);
+		if (instance) {
+			retval = zend_std_read_property(instance, name, type, cache_slot, rv);
+			if (retval == &EG(uninitialized_zval)) {
+				ZVAL_NULL(rv);
+				retval = rv;
 			}
+			return retval;
 		}
 	}
 
@@ -1262,14 +1274,10 @@ found:;
 	/* For initialized lazy proxies: if the real instance's __set guard
 	 * is already set, we are inside a recursive call from the real
 	 * instance's __set. Forward directly to avoid double invocation. */
-	if (UNEXPECTED(zend_object_is_lazy_proxy(zobj)
-			&& zend_lazy_object_initialized(zobj))) {
-		zend_object *instance = zend_lazy_object_get_instance(zobj);
-		if (instance->ce->ce_flags & ZEND_ACC_USE_GUARDS) {
-			uint32_t *instance_guard = zend_get_property_guard(instance, name);
-			if ((*instance_guard) & IN_SET) {
-				return zend_std_write_property(instance, name, value, cache_slot);
-			}
+	{
+		zend_object *instance = zend_lazy_proxy_get_guarded_instance(zobj, name, IN_SET);
+		if (instance) {
+			return zend_std_write_property(instance, name, value, cache_slot);
 		}
 	}
 
@@ -1670,15 +1678,11 @@ ZEND_API void zend_std_unset_property(zend_object *zobj, zend_string *name, void
 	/* For initialized lazy proxies: if the real instance's __unset guard
 	 * is already set, we are inside a recursive call from the real
 	 * instance's __unset. Forward directly to avoid double invocation. */
-	if (UNEXPECTED(zend_object_is_lazy_proxy(zobj)
-			&& zend_lazy_object_initialized(zobj))) {
-		zend_object *instance = zend_lazy_object_get_instance(zobj);
-		if (instance->ce->ce_flags & ZEND_ACC_USE_GUARDS) {
-			uint32_t *instance_guard = zend_get_property_guard(instance, name);
-			if ((*instance_guard) & IN_UNSET) {
-				zend_std_unset_property(instance, name, cache_slot);
-				return;
-			}
+	{
+		zend_object *instance = zend_lazy_proxy_get_guarded_instance(zobj, name, IN_UNSET);
+		if (instance) {
+			zend_std_unset_property(instance, name, cache_slot);
+			return;
 		}
 	}
 
@@ -2498,14 +2502,10 @@ ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has
 	/* For initialized lazy proxies: if the real instance's __isset guard
 	 * is already set, we are inside a recursive call from the real
 	 * instance's __isset. Forward directly to avoid double invocation. */
-	if (UNEXPECTED(zend_object_is_lazy_proxy(zobj)
-			&& zend_lazy_object_initialized(zobj))) {
-		zend_object *instance = zend_lazy_object_get_instance(zobj);
-		if (instance->ce->ce_flags & ZEND_ACC_USE_GUARDS) {
-			uint32_t *instance_guard = zend_get_property_guard(instance, name);
-			if ((*instance_guard) & IN_ISSET) {
-				return zend_std_has_property(instance, name, has_set_exists, cache_slot);
-			}
+	{
+		zend_object *instance = zend_lazy_proxy_get_guarded_instance(zobj, name, IN_ISSET);
+		if (instance) {
+			return zend_std_has_property(instance, name, has_set_exists, cache_slot);
 		}
 	}