diff options
Diffstat (limited to 'Zend/zend_execute.c')
-rw-r--r-- | Zend/zend_execute.c | 60 |
1 files changed, 39 insertions, 21 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index eb61393b69..a64ba0db7f 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1656,37 +1656,55 @@ do_fcall_common: zend_ptr_stack_push(&EG(argument_stack), valptr); } NEXT_OPCODE(); - case ZEND_SEND_VAR: case ZEND_SEND_VAR_NO_REF: - if (opline->extended_value==ZEND_DO_FCALL_BY_NAME - && ARG_SHOULD_BE_SENT_BY_REF(opline->op2.u.opline_num, fbc, fbc->common.arg_types)) { - if (opline->opcode==ZEND_SEND_VAR_NO_REF) { - zend_error(E_ERROR, "Only variables can be passed by reference"); + if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */ + if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) { + goto send_by_var; } - goto send_by_ref; + } else if (!ARG_SHOULD_BE_SENT_BY_REF(opline->op2.u.opline_num, fbc, fbc->common.arg_types)) { + goto send_by_var; } { zval *varptr; varptr = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R); - if (varptr == &EG(uninitialized_zval)) { - ALLOC_ZVAL(varptr); - INIT_ZVAL(*varptr); - varptr->refcount = 0; - } else if (PZVAL_IS_REF(varptr)) { - zval *original_var = varptr; - - ALLOC_ZVAL(varptr); - *varptr = *original_var; - varptr->is_ref = 0; - varptr->refcount = 0; - zval_copy_ctor(varptr); + if (varptr != &EG(uninitialized_zval) && (PZVAL_IS_REF(varptr) || varptr->refcount == 1)) { + varptr->is_ref = 1; + varptr->refcount++; + zend_ptr_stack_push(&EG(argument_stack), varptr); + NEXT_OPCODE(); } - varptr->refcount++; - zend_ptr_stack_push(&EG(argument_stack), varptr); - FREE_OP(&opline->op1, EG(free_op1)); /* for string offsets */ + zend_error(E_ERROR, "Only variables can be passed by reference"); } NEXT_OPCODE(); + case ZEND_SEND_VAR: + if ((opline->extended_value == ZEND_DO_FCALL_BY_NAME) + && ARG_SHOULD_BE_SENT_BY_REF(opline->op2.u.opline_num, fbc, fbc->common.arg_types)) { + goto send_by_ref; + } +send_by_var: + { + zval *varptr; + varptr = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R); + + if (varptr == &EG(uninitialized_zval)) { + ALLOC_ZVAL(varptr); + INIT_ZVAL(*varptr); + varptr->refcount = 0; + } else if (PZVAL_IS_REF(varptr)) { + zval *original_var = varptr; + + ALLOC_ZVAL(varptr); + *varptr = *original_var; + varptr->is_ref = 0; + varptr->refcount = 0; + zval_copy_ctor(varptr); + } + varptr->refcount++; + zend_ptr_stack_push(&EG(argument_stack), varptr); + FREE_OP(&opline->op1, EG(free_op1)); /* for string offsets */ + } + NEXT_OPCODE(); send_by_ref: case ZEND_SEND_REF: { zval **varptr_ptr; |