Commit 3cb85cc681a for php.net
commit 3cb85cc681ac5f1120773917c8f089c898739f98
Author: Ilija Tovilo <ilija.tovilo@me.com>
Date: Tue Feb 3 21:47:27 2026 +0100
Fix assign-op/inc/dec on untyped hooked property backing value
Fixes OSS-Fuzz #478009707
Closes GH-21124
diff --git a/NEWS b/NEWS
index 81d0a689972..dd9fd9a2686 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,8 @@ PHP NEWS
by setRawValueWithoutLazyInitialization() and newLazyGhost()). (Arnaud)
. Fixed bug GH-20504 (Assertion failure in zend_get_property_guard when
accessing properties on Reflection LazyProxy via isset()). (Arnaud)
+ . Fixed OSS-Fuzz #478009707 (Borked assign-op/inc/dec on untyped hooked
+ property backing value). (ilutov)
- Curl:
. Fixed bug GH-21023 (CURLOPT_XFERINFOFUNCTION crash with a null callback).
diff --git a/Zend/tests/oss-fuzz-478009707.phpt b/Zend/tests/oss-fuzz-478009707.phpt
new file mode 100644
index 00000000000..02ba186a49e
--- /dev/null
+++ b/Zend/tests/oss-fuzz-478009707.phpt
@@ -0,0 +1,23 @@
+--TEST--
+OSS-Fuzz #478009707: Assign-op/inc/dec on untyped hooked property backing value
+--FILE--
+<?php
+
+class C {
+ public $prop {
+ set {
+ $this->prop = $value;
+ $this->prop += 1;
+ $this->prop++;
+ ++$this->prop;
+ }
+ }
+}
+
+$c = new C(1);
+$c->prop = 1;
+var_dump($c->prop);
+
+?>
+--EXPECT--
+int(4)
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 3e1026ef60e..4ecd80837b1 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -1070,7 +1070,7 @@ ZEND_VM_C_LABEL(assign_op_object):
}
prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
- if (prop_info) {
+ if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) {
/* special case for typed properties */
zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC);
} else {
@@ -1326,7 +1326,8 @@ ZEND_VM_C_LABEL(pre_incdec_object):
}
} else {
prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2);
- zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+ zend_pre_incdec_property_zval(zptr,
+ prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
}
} else {
zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
@@ -1394,7 +1395,8 @@ ZEND_VM_C_LABEL(post_incdec_object):
ZVAL_NULL(EX_VAR(opline->result.var));
} else {
prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
- zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
+ zend_post_incdec_property_zval(zptr,
+ prop_info && ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
}
} else {
zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 46c04bdd6d2..d7c14a7cf80 100644
Binary files a/Zend/zend_vm_execute.h and b/Zend/zend_vm_execute.h differ