Commit 7c94b351dbb for php.net

commit 7c94b351dbb44f51cf210540f49cddae64fe2037
Author: Lazizbek Ergashev <lazerg2@gmail.com>
Date:   Fri Sep 11 03:06:11 2026 +0500

    Fix GH-23644: crash on a constant-vs-constant empty array comparison

    Co-authored-by: ndossche <7771979+ndossche@users.noreply.github.com>

diff --git a/NEWS b/NEWS
index 8c4131fd642..47e627b104b 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,8 @@ PHP                                                                        NEWS
 - Core:
   . Fixed incorrect internal pointer and foreach iterator positions when
     compacting arrays with holes. (Weilin Du)
+  . Fixed bug GH-23644 (Optimizer leaves a constant-vs-constant comparison
+    unfolded, crashing the VM in zval_undefined_cv). (ndossche)

 - DOM:
   . Fixed use-after-free when re-constructing a DOMXPath whose php:function
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 90a666ab71e..27b0e44218f 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -10105,7 +10105,7 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL|ZEND_IS_NOT_IDENTICAL, (op1_info
 	ZEND_VM_SMART_BRANCH(result, 0);
 }

-ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_IDENTICAL, op->op2_type == IS_CONST && (Z_TYPE_P(RT_CONSTANT(op, op->op2)) == IS_ARRAY && zend_hash_num_elements(Z_ARR_P(RT_CONSTANT(op, op->op2))) == 0), ZEND_IS_IDENTICAL_EMPTY_ARRAY, TMPVARCV, CONST, SPEC(SMART_BRANCH,COMMUTATIVE))
+ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_IDENTICAL, op->op2_type == IS_CONST && (Z_TYPE_P(RT_CONSTANT(op, op->op2)) == IS_ARRAY && zend_hash_num_elements(Z_ARR_P(RT_CONSTANT(op, op->op2))) == 0), ZEND_IS_IDENTICAL_EMPTY_ARRAY, TMPVARCV, CONST, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
 {
 	USE_OPLINE
 	zval *op1;
@@ -10118,7 +10118,7 @@ ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_IDENTICAL, op->op2_type == IS_CONST && (Z_TYPE
 	ZEND_VM_SMART_BRANCH(result, 0);
 }

-ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_NOT_IDENTICAL, op->op2_type == IS_CONST && (Z_TYPE_P(RT_CONSTANT(op, op->op2)) == IS_ARRAY && zend_hash_num_elements(Z_ARR_P(RT_CONSTANT(op, op->op2))) == 0), ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY, TMPVARCV, CONST, SPEC(SMART_BRANCH,COMMUTATIVE))
+ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_NOT_IDENTICAL, op->op2_type == IS_CONST && (Z_TYPE_P(RT_CONSTANT(op, op->op2)) == IS_ARRAY && zend_hash_num_elements(Z_ARR_P(RT_CONSTANT(op, op->op2))) == 0), ZEND_IS_NOT_IDENTICAL_EMPTY_ARRAY, TMPVARCV, CONST, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
 {
 	USE_OPLINE
 	zval *op1;
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 9a98804f25c..2ba4011cf2b 100644
Binary files a/Zend/zend_vm_execute.h and b/Zend/zend_vm_execute.h differ
diff --git a/ext/opcache/tests/opt/gh23644.phpt b/ext/opcache/tests/opt/gh23644.phpt
new file mode 100644
index 00000000000..3094722c32a
--- /dev/null
+++ b/ext/opcache/tests/opt/gh23644.phpt
@@ -0,0 +1,28 @@
+--TEST--
+GH-23644 (Crash on a constant-vs-constant empty array comparison)
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.optimization_level=-1
+--EXTENSIONS--
+opcache
+--CREDITS--
+LTSCommerce
+--FILE--
+<?php
+function f($x) {
+    if (null !== $x || [] !== $x) { return 1; }
+    return 2;
+}
+
+function g($x) {
+    if ($x === null) { return $x === [] ? 'eq' : 'ne'; }
+    return 'other';
+}
+
+var_dump(f(null));
+var_dump(g(null));
+?>
+--EXPECT--
+int(1)
+string(2) "ne"