@@ -1939,109 +1939,142 @@ ZEND_API zend_result ZEND_FASTCALL shift_right_function(zval *result, zval *op1,
1939
1939
1940
1940
ZEND_API zend_result ZEND_FASTCALL concat_function (zval * result , zval * op1 , zval * op2 ) /* {{{ */
1941
1941
{
1942
- zval * orig_op1 = op1 ;
1943
- zval op1_copy , op2_copy ;
1944
-
1945
- ZVAL_UNDEF (& op1_copy );
1946
- ZVAL_UNDEF (& op2_copy );
1942
+ zval * orig_op1 = op1 ;
1943
+ zend_string * op1_string , * op2_string = NULL ;
1944
+ bool free_op1_string = false;
1945
+ bool free_op2_string = false;
1947
1946
1948
1947
do {
1949
- if (UNEXPECTED (Z_TYPE_P (op1 ) != IS_STRING )) {
1948
+ if (EXPECTED (Z_TYPE_P (op1 ) == IS_STRING )) {
1949
+ op1_string = Z_STR_P (op1 );
1950
+ } else {
1950
1951
if (Z_ISREF_P (op1 )) {
1951
1952
op1 = Z_REFVAL_P (op1 );
1952
- if (Z_TYPE_P (op1 ) == IS_STRING ) break ;
1953
+ if (Z_TYPE_P (op1 ) == IS_STRING ) {
1954
+ op1_string = Z_STR_P (op1 );
1955
+ break ;
1956
+ }
1953
1957
}
1954
1958
ZEND_TRY_BINARY_OBJECT_OPERATION (ZEND_CONCAT );
1955
- ZVAL_STR ( & op1_copy , zval_get_string_func (op1 ) );
1959
+ op1_string = zval_get_string_func (op1 );
1956
1960
if (UNEXPECTED (EG (exception ))) {
1957
- zval_ptr_dtor_str ( & op1_copy );
1961
+ zend_string_release ( op1_string );
1958
1962
if (orig_op1 != result ) {
1959
1963
ZVAL_UNDEF (result );
1960
1964
}
1961
1965
return FAILURE ;
1962
1966
}
1967
+ free_op1_string = true;
1963
1968
if (result == op1 ) {
1964
1969
if (UNEXPECTED (op1 == op2 )) {
1965
- op2 = & op1_copy ;
1970
+ op2_string = op1_string ;
1966
1971
}
1967
1972
}
1968
- op1 = & op1_copy ;
1969
1973
}
1970
1974
} while (0 );
1971
1975
do {
1972
- if (UNEXPECTED (Z_TYPE_P (op2 ) != IS_STRING )) {
1973
- if (Z_ISREF_P (op2 )) {
1974
- op2 = Z_REFVAL_P (op2 );
1975
- if (Z_TYPE_P (op2 ) == IS_STRING ) break ;
1976
- }
1977
- ZEND_TRY_BINARY_OP2_OBJECT_OPERATION (ZEND_CONCAT );
1978
- ZVAL_STR (& op2_copy , zval_get_string_func (op2 ));
1979
- if (UNEXPECTED (EG (exception ))) {
1980
- zval_ptr_dtor_str (& op1_copy );
1981
- zval_ptr_dtor_str (& op2_copy );
1982
- if (orig_op1 != result ) {
1983
- ZVAL_UNDEF (result );
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
+ }
1984
1986
}
1985
- return FAILURE ;
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 );
1999
+ }
2000
+ return FAILURE ;
2001
+ }
2002
+ free_op2_string = true;
1986
2003
}
1987
- op2 = & op2_copy ;
1988
2004
}
1989
2005
} while (0 );
1990
2006
1991
- if (UNEXPECTED (Z_STRLEN_P ( op1 ) == 0 )) {
1992
- if (EXPECTED (result != op2 )) {
2007
+ if (UNEXPECTED (ZSTR_LEN ( op1_string ) == 0 )) {
2008
+ if (EXPECTED (free_op2_string || result != op2 )) {
1993
2009
if (result == orig_op1 ) {
1994
2010
i_zval_ptr_dtor (result );
1995
2011
}
1996
- ZVAL_COPY (result , op2 );
2012
+ if (free_op2_string ) {
2013
+ ZVAL_STR (result , op2_string );
2014
+ free_op2_string = false;
2015
+ } else {
2016
+ ZVAL_STR_COPY (result , op2_string );
2017
+ }
1997
2018
}
1998
- } else if (UNEXPECTED (Z_STRLEN_P ( op2 ) == 0 )) {
1999
- if (EXPECTED (result != op1 )) {
2019
+ } else if (UNEXPECTED (ZSTR_LEN ( op2_string ) == 0 )) {
2020
+ if (EXPECTED (free_op1_string || result != op1 )) {
2000
2021
if (result == orig_op1 ) {
2001
2022
i_zval_ptr_dtor (result );
2002
2023
}
2003
- ZVAL_COPY (result , op1 );
2024
+ if (free_op1_string ) {
2025
+ ZVAL_STR (result , op1_string );
2026
+ free_op1_string = false;
2027
+ } else {
2028
+ ZVAL_STR_COPY (result , op1_string );
2029
+ }
2004
2030
}
2005
2031
} else {
2006
- size_t op1_len = Z_STRLEN_P ( op1 );
2007
- size_t op2_len = Z_STRLEN_P ( op2 );
2032
+ size_t op1_len = ZSTR_LEN ( op1_string );
2033
+ size_t op2_len = ZSTR_LEN ( op2_string );
2008
2034
size_t result_len = op1_len + op2_len ;
2009
2035
zend_string * result_str ;
2010
2036
uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH (Z_STR_P (op1 ), Z_STR_P (op2 ));
2011
2037
2012
2038
if (UNEXPECTED (op1_len > ZSTR_MAX_LEN - op2_len )) {
2039
+ if (free_op1_string ) zend_string_release (op1_string );
2040
+ if (free_op2_string ) zend_string_release (op2_string );
2013
2041
zend_throw_error (NULL , "String size overflow" );
2014
- zval_ptr_dtor_str (& op1_copy );
2015
- zval_ptr_dtor_str (& op2_copy );
2016
2042
if (orig_op1 != result ) {
2017
2043
ZVAL_UNDEF (result );
2018
2044
}
2019
2045
return FAILURE ;
2020
2046
}
2021
2047
2022
- if (result == op1 && Z_REFCOUNTED_P (result )) {
2048
+ if (result == op1 ) {
2049
+ if (free_op1_string ) {
2050
+ i_zval_ptr_dtor (result );
2051
+ free_op1_string = false;
2052
+ }
2023
2053
/* special case, perform operations on result */
2024
- result_str = zend_string_extend (Z_STR_P (result ), result_len , 0 );
2054
+ result_str = zend_string_extend (op1_string , result_len , 0 );
2055
+ /* account for the case where result_str == op1_string == op2_string and the realloc is done */
2056
+ if (op1_string == op2_string ) {
2057
+ if (free_op2_string ) zend_string_release (op2_string );
2058
+ op2_string = result_str ;
2059
+ free_op2_string = false;
2060
+ }
2025
2061
} else {
2026
2062
result_str = zend_string_alloc (result_len , 0 );
2027
- memcpy (ZSTR_VAL (result_str ), Z_STRVAL_P ( op1 ), op1_len );
2063
+ memcpy (ZSTR_VAL (result_str ), ZSTR_VAL ( op1_string ), op1_len );
2028
2064
if (result == orig_op1 ) {
2029
2065
i_zval_ptr_dtor (result );
2030
2066
}
2031
2067
}
2032
2068
GC_ADD_FLAGS (result_str , flags );
2033
2069
2034
- /* This has to happen first to account for the cases where result == op1 == op2 and
2035
- * the realloc is done. In this case this line will also update Z_STRVAL_P(op2) to
2036
- * point to the new string. The first op2_len bytes of result will still be the same. */
2037
2070
ZVAL_NEW_STR (result , result_str );
2038
-
2039
- memcpy (ZSTR_VAL (result_str ) + op1_len , Z_STRVAL_P (op2 ), op2_len );
2071
+ memcpy (ZSTR_VAL (result_str ) + op1_len , ZSTR_VAL (op2_string ), op2_len );
2040
2072
ZSTR_VAL (result_str )[result_len ] = '\0' ;
2041
2073
}
2042
2074
2043
- zval_ptr_dtor_str (& op1_copy );
2044
- zval_ptr_dtor_str (& op2_copy );
2075
+ if (free_op1_string ) zend_string_release (op1_string );
2076
+ if (free_op2_string ) zend_string_release (op2_string );
2077
+
2045
2078
return SUCCESS ;
2046
2079
}
2047
2080
/* }}} */
0 commit comments