@@ -1940,7 +1940,7 @@ ZEND_API zend_result ZEND_FASTCALL shift_right_function(zval *result, zval *op1,
1940
1940
ZEND_API zend_result ZEND_FASTCALL concat_function (zval * result , zval * op1 , zval * op2 ) /* {{{ */
1941
1941
{
1942
1942
zval * orig_op1 = op1 ;
1943
- zend_string * op1_string , * op2_string = NULL ;
1943
+ zend_string * op1_string , * op2_string ;
1944
1944
bool free_op1_string = false;
1945
1945
bool free_op2_string = false;
1946
1946
@@ -1968,48 +1968,49 @@ ZEND_API zend_result ZEND_FASTCALL concat_function(zval *result, zval *op1, zval
1968
1968
if (result == op1 ) {
1969
1969
if (UNEXPECTED (op1 == op2 )) {
1970
1970
op2_string = op1_string ;
1971
+ goto has_op2_string ;
1971
1972
}
1972
1973
}
1973
1974
}
1974
1975
} while (0 );
1975
1976
do {
1976
- if (!op2_string ) {
1977
- if (EXPECTED (Z_TYPE_P (op2 ) == IS_STRING )) {
1978
- op2_string = Z_STR_P (op2 );
1979
- } else {
1980
- if (Z_ISREF_P (op2 )) {
1981
- op2 = Z_REFVAL_P (op2 );
1982
- if (Z_TYPE_P (op2 ) == IS_STRING ) {
1983
- op2_string = Z_STR_P (op2 );
1984
- break ;
1985
- }
1986
- }
1987
- /* hold an additional reference because a userland function could free this */
1988
- if (!free_op1_string ) {
1989
- op1_string = zend_string_copy (op1_string );
1990
- free_op1_string = true;
1977
+ if (EXPECTED (Z_TYPE_P (op2 ) == IS_STRING )) {
1978
+ op2_string = Z_STR_P (op2 );
1979
+ } else {
1980
+ if (Z_ISREF_P (op2 )) {
1981
+ op2 = Z_REFVAL_P (op2 );
1982
+ if (Z_TYPE_P (op2 ) == IS_STRING ) {
1983
+ op2_string = Z_STR_P (op2 );
1984
+ break ;
1991
1985
}
1992
- ZEND_TRY_BINARY_OP2_OBJECT_OPERATION (ZEND_CONCAT );
1993
- op2_string = zval_get_string_func (op2 );
1994
- if (UNEXPECTED (EG (exception ))) {
1995
- zend_string_release (op1_string );
1996
- zend_string_release (op2_string );
1997
- if (orig_op1 != result ) {
1998
- ZVAL_UNDEF (result );
1999
- }
2000
- return FAILURE ;
1986
+ }
1987
+ /* hold an additional reference because a userland function could free this */
1988
+ if (!free_op1_string ) {
1989
+ op1_string = zend_string_copy (op1_string );
1990
+ free_op1_string = true;
1991
+ }
1992
+ ZEND_TRY_BINARY_OP2_OBJECT_OPERATION (ZEND_CONCAT );
1993
+ op2_string = zval_get_string_func (op2 );
1994
+ if (UNEXPECTED (EG (exception ))) {
1995
+ zend_string_release (op1_string );
1996
+ zend_string_release (op2_string );
1997
+ if (orig_op1 != result ) {
1998
+ ZVAL_UNDEF (result );
2001
1999
}
2002
- free_op2_string = true ;
2000
+ return FAILURE ;
2003
2001
}
2002
+ free_op2_string = true;
2004
2003
}
2005
2004
} while (0 );
2006
2005
2006
+ has_op2_string :;
2007
2007
if (UNEXPECTED (ZSTR_LEN (op1_string ) == 0 )) {
2008
2008
if (EXPECTED (free_op2_string || result != op2 )) {
2009
2009
if (result == orig_op1 ) {
2010
2010
i_zval_ptr_dtor (result );
2011
2011
}
2012
2012
if (free_op2_string ) {
2013
+ /* transfer ownership of op2_string */
2013
2014
ZVAL_STR (result , op2_string );
2014
2015
free_op2_string = false;
2015
2016
} else {
@@ -2022,6 +2023,7 @@ ZEND_API zend_result ZEND_FASTCALL concat_function(zval *result, zval *op1, zval
2022
2023
i_zval_ptr_dtor (result );
2023
2024
}
2024
2025
if (free_op1_string ) {
2026
+ /* transfer ownership of op1_string */
2025
2027
ZVAL_STR (result , op1_string );
2026
2028
free_op1_string = false;
2027
2029
} else {
@@ -2047,16 +2049,19 @@ ZEND_API zend_result ZEND_FASTCALL concat_function(zval *result, zval *op1, zval
2047
2049
2048
2050
if (result == op1 ) {
2049
2051
if (free_op1_string ) {
2052
+ /* op1_string will be used as the result, so we should not free it */
2050
2053
i_zval_ptr_dtor (result );
2051
2054
free_op1_string = false;
2052
2055
}
2053
2056
/* special case, perform operations on result */
2054
2057
result_str = zend_string_extend (op1_string , result_len , 0 );
2055
2058
/* account for the case where result_str == op1_string == op2_string and the realloc is done */
2056
2059
if (op1_string == op2_string ) {
2057
- if (free_op2_string ) zend_string_release (op2_string );
2060
+ if (free_op2_string ) {
2061
+ zend_string_release (op2_string );
2062
+ free_op2_string = false;
2063
+ }
2058
2064
op2_string = result_str ;
2059
- free_op2_string = false;
2060
2065
}
2061
2066
} else {
2062
2067
result_str = zend_string_alloc (result_len , 0 );
0 commit comments