From 7f68a7afe625ffdc485a05d417197bc30cbb1513 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 17 Feb 2021 11:51:13 +0300 Subject: [PATCH] Fixed bug #80745 (JIT produces Assert failure and UNKNOWN:0 var_dumps in code involving bitshifts) --- NEWS | 2 ++ ext/opcache/jit/zend_jit.c | 36 ++++++++++++++++++++++-- ext/opcache/jit/zend_jit_trace.c | 33 ++++++++++++++++------ ext/opcache/tests/jit/bug80745.phpt | 43 +++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 12 deletions(-) create mode 100644 ext/opcache/tests/jit/bug80745.phpt diff --git a/NEWS b/NEWS index d8a37b4323..63901ebd5e 100644 --- a/NEWS +++ b/NEWS @@ -28,6 +28,8 @@ PHP NEWS . Fixed bug #80682 (opcache doesn't honour pcre.jit option). (Remi) . Fixed bug #80742 (Opcache JIT makes some boolean logic unexpectedly be true). (Dmitry) + . Fixed bug #80745 (JIT produces Assert failure and UNKNOWN:0 var_dumps in + code involving bitshifts). (Dmitry) - OpenSSL: . Fixed bug #80747 (Providing RSA key size < 512 generates key that crash diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index 1306bb36ba..7513abbf9b 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -2303,7 +2303,17 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op break; } if (opline->result_type != IS_UNUSED) { - res_use_info = RES_USE_INFO(); + res_use_info = -1; + + if (opline->result_type == IS_CV) { + zend_jit_addr res_use_addr = RES_USE_REG_ADDR(); + + if (Z_MODE(res_use_addr) != IS_REG + || Z_LOAD(res_use_addr) + || Z_STORE(res_use_addr)) { + res_use_info = RES_USE_INFO(); + } + } res_info = RES_INFO(); res_addr = RES_REG_ADDR(); } else { @@ -2354,7 +2364,17 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op goto jit_failure; } } else { - res_use_info = RES_USE_INFO(); + res_use_info = -1; + + if (opline->result_type == IS_CV) { + zend_jit_addr res_use_addr = RES_USE_REG_ADDR(); + + if (Z_MODE(res_use_addr) != IS_REG + || Z_LOAD(res_use_addr) + || Z_STORE(res_use_addr)) { + res_use_info = RES_USE_INFO(); + } + } } if (!zend_jit_long_math(&dasm_state, opline, op1_info, OP1_RANGE(), OP1_REG_ADDR(), @@ -2398,7 +2418,17 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op goto jit_failure; } } else { - res_use_info = RES_USE_INFO(); + res_use_info = -1; + + if (opline->result_type == IS_CV) { + zend_jit_addr res_use_addr = RES_USE_REG_ADDR(); + + if (Z_MODE(res_use_addr) != IS_REG + || Z_LOAD(res_use_addr) + || Z_STORE(res_use_addr)) { + res_use_info = RES_USE_INFO(); + } + } } res_info = RES_INFO(); if (opline->opcode == ZEND_ADD && diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index 69c4f79fa8..8353c3cec0 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -3878,10 +3878,15 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par STACK_MEM_TYPE(stack, EX_VAR_TO_NUM(opline->result.var))) & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE); #else + res_use_info = -1; if (opline->result_type == IS_CV) { - res_use_info = RES_USE_INFO(); - } else { - res_use_info = MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE; + zend_jit_addr res_use_addr = RES_USE_REG_ADDR(); + + if (Z_MODE(res_use_addr) != IS_REG + || Z_LOAD(res_use_addr) + || Z_STORE(res_use_addr)) { + res_use_info = RES_USE_INFO(); + } } #endif res_info = RES_INFO(); @@ -3973,10 +3978,15 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par STACK_MEM_TYPE(stack, EX_VAR_TO_NUM(opline->result.var))) & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE); #else + res_use_info = -1; if (opline->result_type == IS_CV) { - res_use_info = RES_USE_INFO(); - } else { - res_use_info = MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE; + zend_jit_addr res_use_addr = RES_USE_REG_ADDR(); + + if (Z_MODE(res_use_addr) != IS_REG + || Z_LOAD(res_use_addr) + || Z_STORE(res_use_addr)) { + res_use_info = RES_USE_INFO(); + } } #endif } @@ -4050,10 +4060,15 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par STACK_MEM_TYPE(stack, EX_VAR_TO_NUM(opline->result.var))) & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE); #else + res_use_info = -1; if (opline->result_type == IS_CV) { - res_use_info = RES_USE_INFO(); - } else { - res_use_info = MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE; + zend_jit_addr res_use_addr = RES_USE_REG_ADDR(); + + if (Z_MODE(res_use_addr) != IS_REG + || Z_LOAD(res_use_addr) + || Z_STORE(res_use_addr)) { + res_use_info = RES_USE_INFO(); + } } #endif } diff --git a/ext/opcache/tests/jit/bug80745.phpt b/ext/opcache/tests/jit/bug80745.phpt new file mode 100644 index 0000000000..66956f4139 --- /dev/null +++ b/ext/opcache/tests/jit/bug80745.phpt @@ -0,0 +1,43 @@ +--TEST-- +Bug #80745 (JIT produces Assert failure and UNKNOWN:0 var_dumps in code involving bitshifts) +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit=function +opcache.jit_buffer_size=1M +opcache.protect_memory=1 +--SKIPIF-- + +--FILE-- +qr ? 1 : 0); + $flags = ($flags << 4) | $message->opcode; + var_dump($flags); + $flags = ($flags << 1) | ($message->aa ? 1 : 0); +} + +headerToBinary(new Message()); + +echo "PROBLEM NOT REPRODUCED !\n"; +?> +--EXPECT-- +Starting... +int(0) +PROBLEM NOT REPRODUCED ! + -- 2.40.0