From 6893f1f98e1c73d4eece1827f0dc4fedc059a67d Mon Sep 17 00:00:00 2001
From: Nikita Popov <nikita.ppv@gmail.com>
Date: Tue, 28 May 2019 15:45:19 +0200
Subject: [PATCH] SCCP: Don't perform partial object propagation for typed
 props

---
 ext/opcache/Optimizer/sccp.c        | 11 ++++++++++-
 ext/opcache/tests/opt/sccp_028.phpt | 25 +++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 1 deletion(-)
 create mode 100644 ext/opcache/tests/opt/sccp_028.phpt

diff --git a/ext/opcache/Optimizer/sccp.c b/ext/opcache/Optimizer/sccp.c
index 47846fec8e..e81c99d61b 100644
--- a/ext/opcache/Optimizer/sccp.c
+++ b/ext/opcache/Optimizer/sccp.c
@@ -1207,9 +1207,18 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
 			if (ssa_op->op1_def >= 0
 					&& ctx->scdf.ssa->vars[ssa_op->op1_def].escape_state == ESCAPE_STATE_NO_ESCAPE) {
 				zval *data = get_op1_value(ctx, opline+1, ssa_op+1);
+				zend_ssa_var_info *var_info = &ctx->scdf.ssa->var_info[ssa_op->op1_use];
+
+				/* Don't try to propagate assignments to (potentially) typed properties. We would
+				 * need to deal with errors and type conversions first. */
+				if (!var_info->ce || (var_info->ce->ce_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
+					SET_RESULT_BOT(result);
+					SET_RESULT_BOT(op1);
+					return;
+				}
 
 				/* If $a in $a->foo=$c is UNDEF, treat it like NULL. There is no warning. */
-				if ((ctx->scdf.ssa->var_info[ssa_op->op1_use].type & MAY_BE_ANY) == 0) {
+				if ((var_info->type & MAY_BE_ANY) == 0) {
 					op1 = &EG(uninitialized_zval);
 				}
 
diff --git a/ext/opcache/tests/opt/sccp_028.phpt b/ext/opcache/tests/opt/sccp_028.phpt
new file mode 100644
index 0000000000..a916b3af14
--- /dev/null
+++ b/ext/opcache/tests/opt/sccp_028.phpt
@@ -0,0 +1,25 @@
+--TEST--
+SCCP 028: Don't propagate typed properties
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.optimization_level=-1
+opcache.preload=
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+
+class Foo {
+    public int $bar = 1;
+}
+function test() {
+    $foo = new Foo();
+    $foo->bar = "10";
+    var_dump($foo->bar);
+}
+test();
+
+?>
+--EXPECT--
+int(10)
-- 
2.40.0