From a2c41c0ea6e6b6afbfaaeae25e66fd17e746a98a Mon Sep 17 00:00:00 2001 From: Tyson Andre Date: Fri, 15 Nov 2019 12:47:32 -0500 Subject: Fix $x = (bool)$x; for undefined with opcache And `$x = !$x` Noticed while working on GH-4912 The included test would not emit undefined variable errors in php 8.0 with opcache enabled. The command used: ``` php -d zend_extension=opcache.so --no-php-ini -d error_reporting=E_ALL \ -d opcache.file_cache= -d opcache.enable_cli=1 test.php ``` --- Zend/zend_vm_def.h | 8 ++++++-- Zend/zend_vm_execute.h | 24 ++++++++++++++++++------ ext/opcache/tests/bool_not_cv.phpt | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 ext/opcache/tests/bool_not_cv.phpt diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index e4431e6a3a..ed84d17bb8 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -758,8 +758,10 @@ ZEND_VM_HANDLER(13, ZEND_BOOL_NOT, CONST|TMPVAR|CV, ANY) if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_FALSE(EX_VAR(opline->result.var)); } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + /* The result and op1 can be the same cv zval */ + const uint32_t orig_val_type = Z_TYPE_INFO_P(val); ZVAL_TRUE(EX_VAR(opline->result.var)); - if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + if (OP1_TYPE == IS_CV && UNEXPECTED(orig_val_type == IS_UNDEF)) { SAVE_OPLINE(); GET_OP1_UNDEF_CV(val, BP_VAR_R); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -4755,8 +4757,10 @@ ZEND_VM_HANDLER(52, ZEND_BOOL, CONST|TMPVAR|CV, ANY) if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_TRUE(EX_VAR(opline->result.var)); } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + /* The result and op1 can be the same cv zval */ + const uint32_t orig_val_type = Z_TYPE_INFO_P(val); ZVAL_FALSE(EX_VAR(opline->result.var)); - if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + if (OP1_TYPE == IS_CV && UNEXPECTED(orig_val_type == IS_UNDEF)) { SAVE_OPLINE(); GET_OP1_UNDEF_CV(val, BP_VAR_R); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index d313e9502d..3f975dec0b 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2653,8 +2653,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CONST_HANDLER(ZE if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_FALSE(EX_VAR(opline->result.var)); } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + /* The result and op1 can be the same cv zval */ + const uint32_t orig_val_type = Z_TYPE_INFO_P(val); ZVAL_TRUE(EX_VAR(opline->result.var)); - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + if (IS_CONST == IS_CV && UNEXPECTED(orig_val_type == IS_UNDEF)) { SAVE_OPLINE(); GET_OP1_UNDEF_CV(val, BP_VAR_R); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -3185,8 +3187,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_CONST_HANDLER(ZEND_O if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_TRUE(EX_VAR(opline->result.var)); } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + /* The result and op1 can be the same cv zval */ + const uint32_t orig_val_type = Z_TYPE_INFO_P(val); ZVAL_FALSE(EX_VAR(opline->result.var)); - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + if (IS_CONST == IS_CV && UNEXPECTED(orig_val_type == IS_UNDEF)) { SAVE_OPLINE(); GET_OP1_UNDEF_CV(val, BP_VAR_R); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -32866,8 +32870,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CV_HANDLER(ZEND_ if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_FALSE(EX_VAR(opline->result.var)); } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + /* The result and op1 can be the same cv zval */ + const uint32_t orig_val_type = Z_TYPE_INFO_P(val); ZVAL_TRUE(EX_VAR(opline->result.var)); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(orig_val_type == IS_UNDEF)) { SAVE_OPLINE(); GET_OP1_UNDEF_CV(val, BP_VAR_R); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -33704,8 +33710,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_CV_HANDLER(ZEND_OPCO if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_TRUE(EX_VAR(opline->result.var)); } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + /* The result and op1 can be the same cv zval */ + const uint32_t orig_val_type = Z_TYPE_INFO_P(val); ZVAL_FALSE(EX_VAR(opline->result.var)); - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + if (IS_CV == IS_CV && UNEXPECTED(orig_val_type == IS_UNDEF)) { SAVE_OPLINE(); GET_OP1_UNDEF_CV(val, BP_VAR_R); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -48537,8 +48545,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER(Z if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_FALSE(EX_VAR(opline->result.var)); } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + /* The result and op1 can be the same cv zval */ + const uint32_t orig_val_type = Z_TYPE_INFO_P(val); ZVAL_TRUE(EX_VAR(opline->result.var)); - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(orig_val_type == IS_UNDEF)) { SAVE_OPLINE(); GET_OP1_UNDEF_CV(val, BP_VAR_R); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -48801,8 +48811,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_TMPVAR_HANDLER(ZEND_ if (Z_TYPE_INFO_P(val) == IS_TRUE) { ZVAL_TRUE(EX_VAR(opline->result.var)); } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { + /* The result and op1 can be the same cv zval */ + const uint32_t orig_val_type = Z_TYPE_INFO_P(val); ZVAL_FALSE(EX_VAR(opline->result.var)); - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { + if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(orig_val_type == IS_UNDEF)) { SAVE_OPLINE(); GET_OP1_UNDEF_CV(val, BP_VAR_R); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); diff --git a/ext/opcache/tests/bool_not_cv.phpt b/ext/opcache/tests/bool_not_cv.phpt new file mode 100644 index 0000000000..ed3cf83514 --- /dev/null +++ b/ext/opcache/tests/bool_not_cv.phpt @@ -0,0 +1,34 @@ +--TEST-- +$v = !$v/(bool)$v checks for undefined variables +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_cache_only=0 +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +In undef_negation + +Notice: Undefined variable: v in %s on line 4 +true +In undef_bool_cast + +Notice: Undefined variable: v in %s on line 10 +false -- cgit v1.2.1