@ -378,7 +378,7 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2
*/
/* break missing intentionally */
case IS_CONST :
if ( PZVAL_IS_REF ( value ) ) {
if ( PZVAL_IS_REF ( value ) & & value - > refcount > 0 ) {
variable_ptr = * variable_ptr_ptr = ( zval * ) emalloc ( sizeof ( zval ) ) ;
* variable_ptr = * value ;
zval_copy_ctor ( variable_ptr ) ;
@ -1218,14 +1218,19 @@ binary_assign_op_addr: {
AI_USE_PTR ( Ts [ opline - > result . u . var ] . var ) ;
break ;
case ZEND_ASSIGN : {
zval * value = get_zval_ptr ( & opline - > op2 , Ts , & EG ( free_op2 ) , BP_VAR_R ) ;
zval * value ;
SUSPEND_GARBAGE ( ) ;
value = get_zval_ptr ( & opline - > op2 , Ts , & EG ( free_op2 ) , BP_VAR_R ) ;
RESUME_GARBAGE ( ) ;
zend_assign_to_variable ( & opline - > result , & opline - > op1 , & opline - > op2 , value , ( EG ( free_op2 ) ? IS_TMP_VAR : opline - > op2 . op_type ) , Ts ELS_CC ) ;
/* zend_assign_to_variable() always takes care of op2, never free it! */
}
break ;
case ZEND_ASSIGN_REF :
SUSPEND_GARBAGE ( ) ;
zend_assign_to_variable_reference ( & opline - > result , get_zval_ptr_ptr ( & opline - > op1 , Ts , BP_VAR_W ) , get_zval_ptr_ptr ( & opline - > op2 , Ts , BP_VAR_W ) , Ts ELS_CC ) ;
RESUME_GARBAGE ( ) ;
break ;
case ZEND_JMP :
# if DEBUG_ZEND>=2
@ -1467,16 +1472,23 @@ overloaded_function_call_cont:
}
do_fcall_common :
{
zval * original_return_value ;
zval * * original_return_value ;
int return_value_not_used = ( opline - > result . u . EA . type & EXT_TYPE_UNUSED ) ;
zend_ptr_stack_push ( & EG ( argument_stack ) , ( void * ) opline - > extended_value ) ;
var_uninit ( & Ts [ opline - > result . u . var ] . tmp_var ) ;
Ts [ opline - > result . u . var ] . var . ptr = ( zval * ) emalloc ( sizeof ( zval ) ) ;
Ts [ opline - > result . u . var ] . var . ptr_ptr = & Ts [ opline - > result . u . var ] . var . ptr ;
var_uninit ( Ts [ opline - > result . u . var ] . var . ptr ) ;
Ts [ opline - > result . u . var ] . var . ptr - > is_ref = 0 ;
Ts [ opline - > result . u . var ] . var . ptr - > refcount = 1 ;
if ( function_state . function - > type = = ZEND_INTERNAL_FUNCTION ) {
( ( zend_internal_function * ) function_state . function ) - > handler ( opline - > extended_value , & Ts [ opline - > result . u . var ] . tmp_var , & EG ( regular_list ) , & EG ( persistent_list ) , object . ptr , ! return_value_not_used ) ;
( ( zend_internal_function * ) function_state . function ) - > handler ( opline - > extended_value , Ts [ opline - > result . u . var ] . var . pt r, & EG ( regular_list ) , & EG ( persistent_list ) , object . ptr , ! return_value_not_used ) ;
if ( object . ptr ) {
object . ptr - > refcount - - ;
}
Ts [ opline - > result . u . var ] . var . ptr - > is_ref = 0 ;
Ts [ opline - > result . u . var ] . var . ptr - > refcount = 1 ;
} else if ( function_state . function - > type = = ZEND_USER_FUNCTION ) {
HashTable * calling_symbol_table ;
@ -1502,13 +1514,13 @@ do_fcall_common:
* this_ptr = object . ptr ;
object . ptr = NULL ;
}
original_return_value = EG ( return_value ) ;
EG ( return_value ) = & Ts [ opline - > result . u . var ] . tmp_va r;
original_return_value = EG ( return_value_ptr_ptr ) ;
EG ( return_value_ptr_ptr ) = Ts [ opline - > result . u . var ] . var . ptr_pt r;
EG ( active_op_array ) = ( zend_op_array * ) function_state . function ;
zend_execute ( EG ( active_op_array ) ELS_CC ) ;
EG ( opline_ptr ) = & opline ;
EG ( active_op_array ) = op_array ;
EG ( return_value ) = original_return_value ;
EG ( return_value_ptr_ptr ) = original_return_value ;
if ( EG ( symtable_cache_ptr ) > = EG ( symtable_cache_limit ) ) {
zend_hash_destroy ( function_state . function_symbol_table ) ;
efree ( function_state . function_symbol_table ) ;
@ -1518,11 +1530,11 @@ do_fcall_common:
}
EG ( active_symbol_table ) = calling_symbol_table ;
} else { /* ZEND_OVERLOADED_FUNCTION */
call_overloaded_function ( opline - > extended_value , & Ts [ opline - > result . u . var ] . tmp_va r, & EG ( regular_list ) , & EG ( persistent_list ) ELS_CC ) ;
call_overloaded_function ( opline - > extended_value , Ts [ opline - > result . u . var ] . var . pt r, & EG ( regular_list ) , & EG ( persistent_list ) ELS_CC ) ;
efree ( fbc ) ;
}
if ( return_value_not_used ) {
zendi_z val_dtor ( Ts [ opline - > result . u . var ] . tmp_va r) ;
zval_ptr_ dtor ( & Ts [ opline - > result . u . var ] . var . pt r) ;
}
object . ptr = zend_ptr_stack_pop ( & EG ( arg_types_stack ) ) ;
if ( opline - > opcode = = ZEND_DO_FCALL_BY_NAME ) {
@ -1534,11 +1546,41 @@ do_fcall_common:
}
break ;
case ZEND_RETURN : {
zval * retval = get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ;
zval * retval_ptr ;
zval * * retval_ptr_ptr ;
* EG ( return_value ) = * retval ;
if ( ! EG ( free_op1 ) ) {
zendi_zval_copy_ctor ( * EG ( return_value ) ) ;
if ( ( EG ( active_op_array ) - > return_reference = = ZEND_RETURN_REF ) & &
( opline - > op1 . op_type ! = IS_CONST ) & &
( opline - > op1 . op_type ! = IS_TMP_VAR ) ) {
retval_ptr_ptr = get_zval_ptr_ptr ( & opline - > op1 , Ts , BP_VAR_W ) ;
if ( ! PZVAL_IS_REF ( * retval_ptr_ptr ) ) {
SEPARATE_ZVAL ( retval_ptr_ptr ) ;
( * retval_ptr_ptr ) - > is_ref = 1 ;
}
( * retval_ptr_ptr ) - > refcount + + ;
efree ( * EG ( return_value_ptr_ptr ) ) ;
( * EG ( return_value_ptr_ptr ) ) = ( * retval_ptr_ptr ) ;
} else {
retval_ptr = get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ;
if ( ! EG ( free_op1 ) ) { /* Not a temp var */
if ( PZVAL_IS_REF ( retval_ptr ) & & retval_ptr - > refcount > 0 ) {
* * EG ( return_value_ptr_ptr ) = * retval_ptr ;
( * EG ( return_value_ptr_ptr ) ) - > is_ref = 0 ;
( * EG ( return_value_ptr_ptr ) ) - > refcount = 1 ;
zval_copy_ctor ( * EG ( return_value_ptr_ptr ) ) ;
} else {
efree ( * EG ( return_value_ptr_ptr ) ) ;
* EG ( return_value_ptr_ptr ) = retval_ptr ;
retval_ptr - > refcount + + ;
}
} else {
* * EG ( return_value_ptr_ptr ) = * retval_ptr ;
( * EG ( return_value_ptr_ptr ) ) - > refcount = 1 ;
( * EG ( return_value_ptr_ptr ) ) - > is_ref = 0 ;
}
}
# if SUPPORT_INTERACTIVE
op_array - > last_executed_op_number = opline - op_array - > opcodes ;
@ -1566,7 +1608,10 @@ do_fcall_common:
goto send_by_ref ;
}
{
zval * varptr = get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ;
zval * varptr ;
SUSPEND_GARBAGE ( ) ;
varptr = get_zval_ptr ( & opline - > op1 , Ts , & EG ( free_op1 ) , BP_VAR_R ) ;
RESUME_GARBAGE ( ) ;
if ( varptr = = & EG ( uninitialized_zval ) ) {
varptr = ( zval * ) emalloc ( sizeof ( zval ) ) ;
@ -1589,8 +1634,13 @@ do_fcall_common:
break ;
send_by_ref :
case ZEND_SEND_REF : {
zval * * varptr_ptr = get_zval_ptr_ptr ( & opline - > op1 , Ts , BP_VAR_W ) ;
zval * varptr = * varptr_ptr ;
zval * * varptr_ptr ;
zval * varptr ;
SUSPEND_GARBAGE ( ) ;
varptr_ptr = get_zval_ptr_ptr ( & opline - > op1 , Ts , BP_VAR_W ) ;
RESUME_GARBAGE ( ) ;
varptr = * varptr_ptr ;
if ( ! PZVAL_IS_REF ( varptr ) ) {
/* code to break away this variable */