From fd463a9a6078074f8f648982b42bdd14423fb614 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Fri, 17 Aug 2018 12:19:31 +0800 Subject: [PATCH] Fixed bug #76752 (Crash in ZEND_COALESCE_SPEC_TMP_HANDLER - assertion in _get_zval_ptr_tmp failed). --- NEWS | 4 ++ Zend/tests/bug76752.phpt | 11 +++ Zend/zend_vm_def.h | 8 +-- Zend/zend_vm_execute.h | 152 ++++++++++++++------------------------- Zend/zend_vm_handlers.h | 4 +- Zend/zend_vm_opcodes.c | 2 +- 6 files changed, 76 insertions(+), 105 deletions(-) create mode 100644 Zend/tests/bug76752.phpt diff --git a/NEWS b/NEWS index 889697dc27..a89679f73c 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 7.3.0beta3 +- Core: + . Fixed bug #76752 (Crash in ZEND_COALESCE_SPEC_TMP_HANDLER - assertion in + _get_zval_ptr_tmp failed). (Laruence) + - Opcache: . Fixed bug #76747 (Opcache treats path containing "test.pharma.tld" as a phar file). (Laruence) diff --git a/Zend/tests/bug76752.phpt b/Zend/tests/bug76752.phpt new file mode 100644 index 0000000000..dcdfeebeb9 --- /dev/null +++ b/Zend/tests/bug76752.phpt @@ -0,0 +1,11 @@ +--TEST-- +Bug #76752 (Crash in ZEND_COALESCE_SPEC_TMP_HANDLER - assertion in _get_zval_ptr_tmp failed) +--FILE-- +prop = &$val; +var_dump($obj->prop ?? []); +?> +--EXPECT-- +string(3) "foo" diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 527aa38074..14dc9e6763 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -6527,7 +6527,7 @@ ZEND_VM_COLD_CONST_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, JMP_ADDR) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_COLD_CONST_HANDLER(169, ZEND_COALESCE, CONST|TMP|VAR|CV, JMP_ADDR) +ZEND_VM_COLD_CONST_HANDLER(169, ZEND_COALESCE, CONST|TMPVAR|CV, JMP_ADDR) { USE_OPLINE zend_free_op free_op1; @@ -6537,8 +6537,8 @@ ZEND_VM_COLD_CONST_HANDLER(169, ZEND_COALESCE, CONST|TMP|VAR|CV, JMP_ADDR) SAVE_OPLINE(); value = GET_OP1_ZVAL_PTR(BP_VAR_IS); - if ((OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) && Z_ISREF_P(value)) { - if (OP1_TYPE == IS_VAR) { + if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + if (OP1_TYPE & IS_VAR) { ref = value; } value = Z_REFVAL_P(value); @@ -6551,7 +6551,7 @@ ZEND_VM_COLD_CONST_HANDLER(169, ZEND_COALESCE, CONST|TMP|VAR|CV, JMP_ADDR) if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); } else if (OP1_TYPE == IS_CV) { if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); - } else if (OP1_TYPE == IS_VAR && ref) { + } else if ((OP1_TYPE & IS_VAR) && ref) { zend_reference *r = Z_REF_P(ref); if (UNEXPECTED(GC_DELREF(r) == 0)) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 85c6c3a49b..523e0985f9 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3545,8 +3545,8 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_CON SAVE_OPLINE(); value = RT_CONSTANT(opline, opline->op1); - if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(value)) { - if (IS_CONST == IS_VAR) { + if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + if (IS_CONST & IS_VAR) { ref = value; } value = Z_REFVAL_P(value); @@ -3559,7 +3559,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_CON if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); } else if (IS_CONST == IS_CV) { if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); - } else if (IS_CONST == IS_VAR && ref) { + } else if ((IS_CONST & IS_VAR) && ref) { zend_reference *r = Z_REF_P(ref); if (UNEXPECTED(GC_DELREF(r) == 0)) { @@ -12781,6 +12781,46 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_EXIT_SPEC_TMPVAR_ ZEND_VM_NEXT_OPCODE(); /* Never reached */ } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *value; + zval *ref = NULL; + + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); + + if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + if ((IS_TMP_VAR|IS_VAR) & IS_VAR) { + ref = value; + } + value = Z_REFVAL_P(value); + } + + if (Z_TYPE_P(value) > IS_NULL) { + zval *result = EX_VAR(opline->result.var); + ZVAL_COPY_VALUE(result, value); + if ((IS_TMP_VAR|IS_VAR) == IS_CONST) { + if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV) { + if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); + } else if (((IS_TMP_VAR|IS_VAR) & IS_VAR) && ref) { + zend_reference *r = Z_REF_P(ref); + + if (UNEXPECTED(GC_DELREF(r) == 0)) { + efree_size(r, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(result)) { + Z_ADDREF_P(result); + } + } + ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); + } + + zval_ptr_dtor_nogc(free_op1); + ZEND_VM_NEXT_OPCODE(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -18393,46 +18433,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *value; - zval *ref = NULL; - - SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(value)) { - if (IS_TMP_VAR == IS_VAR) { - ref = value; - } - value = Z_REFVAL_P(value); - } - - if (Z_TYPE_P(value) > IS_NULL) { - zval *result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, value); - if (IS_TMP_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); - } else if (IS_TMP_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); - } else if (IS_TMP_VAR == IS_VAR && ref) { - zend_reference *r = Z_REF_P(ref); - - if (UNEXPECTED(GC_DELREF(r) == 0)) { - efree_size(r, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(result)) { - Z_ADDREF_P(result); - } - } - ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); - } - - zval_ptr_dtor_nogc(free_op1); - ZEND_VM_NEXT_OPCODE(); -} - static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -21755,46 +21755,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zend_free_op free_op1; - zval *value; - zval *ref = NULL; - - SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var, &free_op1 EXECUTE_DATA_CC); - - if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(value)) { - if (IS_VAR == IS_VAR) { - ref = value; - } - value = Z_REFVAL_P(value); - } - - if (Z_TYPE_P(value) > IS_NULL) { - zval *result = EX_VAR(opline->result.var); - ZVAL_COPY_VALUE(result, value); - if (IS_VAR == IS_CONST) { - if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); - } else if (IS_VAR == IS_CV) { - if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); - } else if (IS_VAR == IS_VAR && ref) { - zend_reference *r = Z_REF_P(ref); - - if (UNEXPECTED(GC_DELREF(r) == 0)) { - efree_size(r, sizeof(zend_reference)); - } else if (Z_OPT_REFCOUNTED_P(result)) { - Z_ADDREF_P(result); - } - } - ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); - } - - zval_ptr_dtor_nogc(free_op1); - ZEND_VM_NEXT_OPCODE(); -} - static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -37965,8 +37925,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_CV_HANDLER(ZEND_ SAVE_OPLINE(); value = _get_zval_ptr_cv_BP_VAR_IS(opline->op1.var EXECUTE_DATA_CC); - if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(value)) { - if (IS_CV == IS_VAR) { + if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) { + if (IS_CV & IS_VAR) { ref = value; } value = Z_REFVAL_P(value); @@ -37979,7 +37939,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COALESCE_SPEC_CV_HANDLER(ZEND_ if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result); } else if (IS_CV == IS_CV) { if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result); - } else if (IS_CV == IS_VAR && ref) { + } else if ((IS_CV & IS_VAR) && ref) { zend_reference *r = Z_REF_P(ref); if (UNEXPECTED(GC_DELREF(r) == 0)) { @@ -54125,8 +54085,8 @@ ZEND_API void execute_ex(zend_execute_data *ex) (void*)&&ZEND_ASSIGN_POW_SPEC_CV_CV_OBJ_LABEL, (void*)&&ZEND_BIND_GLOBAL_SPEC_CV_CONST_LABEL, (void*)&&ZEND_COALESCE_SPEC_CONST_LABEL, - (void*)&&ZEND_COALESCE_SPEC_TMP_LABEL, - (void*)&&ZEND_COALESCE_SPEC_VAR_LABEL, + (void*)&&ZEND_COALESCE_SPEC_TMPVAR_LABEL, + (void*)&&ZEND_COALESCE_SPEC_TMPVAR_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_COALESCE_SPEC_CV_LABEL, (void*)&&ZEND_SPACESHIP_SPEC_CONST_CONST_LABEL, @@ -56879,6 +56839,10 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_EXIT_SPEC_TMPVAR) ZEND_EXIT_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); + HYBRID_CASE(ZEND_COALESCE_SPEC_TMPVAR): + VM_TRACE(ZEND_COALESCE_SPEC_TMPVAR) + ZEND_COALESCE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + HYBRID_BREAK(); HYBRID_CASE(ZEND_STRLEN_SPEC_TMPVAR): VM_TRACE(ZEND_STRLEN_SPEC_TMPVAR) ZEND_STRLEN_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -57441,10 +57405,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_JMP_SET_SPEC_TMP) ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_COALESCE_SPEC_TMP): - VM_TRACE(ZEND_COALESCE_SPEC_TMP) - ZEND_COALESCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_QM_ASSIGN_SPEC_TMP): VM_TRACE(ZEND_QM_ASSIGN_SPEC_TMP) ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -57759,10 +57719,6 @@ zend_leave_helper_SPEC_LABEL: VM_TRACE(ZEND_JMP_SET_SPEC_VAR) ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); - HYBRID_CASE(ZEND_COALESCE_SPEC_VAR): - VM_TRACE(ZEND_COALESCE_SPEC_VAR) - ZEND_COALESCE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - HYBRID_BREAK(); HYBRID_CASE(ZEND_QM_ASSIGN_SPEC_VAR): VM_TRACE(ZEND_QM_ASSIGN_SPEC_VAR) ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -63628,8 +63584,8 @@ void zend_vm_init(void) ZEND_ASSIGN_POW_SPEC_CV_CV_OBJ_HANDLER, ZEND_BIND_GLOBAL_SPEC_CV_CONST_HANDLER, ZEND_COALESCE_SPEC_CONST_HANDLER, - ZEND_COALESCE_SPEC_TMP_HANDLER, - ZEND_COALESCE_SPEC_VAR_HANDLER, + ZEND_COALESCE_SPEC_TMPVAR_HANDLER, + ZEND_COALESCE_SPEC_TMPVAR_HANDLER, ZEND_NULL_HANDLER, ZEND_COALESCE_SPEC_CV_HANDLER, ZEND_SPACESHIP_SPEC_CONST_CONST_HANDLER, diff --git a/Zend/zend_vm_handlers.h b/Zend/zend_vm_handlers.h index 28322c5e02..9e9a360601 100644 --- a/Zend/zend_vm_handlers.h +++ b/Zend/zend_vm_handlers.h @@ -1404,8 +1404,8 @@ _(2738, ZEND_ASSIGN_POW_SPEC_CV_CV_OBJ) \ _(2739, ZEND_BIND_GLOBAL_SPEC_CV_CONST) \ _(2740, ZEND_COALESCE_SPEC_CONST) \ - _(2741, ZEND_COALESCE_SPEC_TMP) \ - _(2742, ZEND_COALESCE_SPEC_VAR) \ + _(2741, ZEND_COALESCE_SPEC_TMPVAR) \ + _(2742, ZEND_COALESCE_SPEC_TMPVAR) \ _(2744, ZEND_COALESCE_SPEC_CV) \ _(2745, ZEND_SPACESHIP_SPEC_CONST_CONST) \ _(2746, ZEND_SPACESHIP_SPEC_CONST_TMPVAR) \ diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index 73a2c164ea..c272f7314a 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -394,7 +394,7 @@ static uint32_t zend_vm_opcodes_flags[199] = { 0x00000707, 0x04046751, 0x00040301, - 0x00002003, + 0x00002007, 0x00000707, 0x03000000, 0x03000303, -- 2.40.0