Skip to content

Instantly share code, notes, and snippets.

@laruence
Created October 23, 2014 09:46
Show Gist options
  • Save laruence/a368a47cbe7b21b96534 to your computer and use it in GitHub Desktop.
Save laruence/a368a47cbe7b21b96534 to your computer and use it in GitHub Desktop.
concat_function
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 03e913c..df918e4 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -1525,36 +1525,40 @@ ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2
ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
- zval op1_copy, op2_copy;
+ zend_string *op1_str, *op2_str;
int use_copy1 = 0, use_copy2 = 0;
- if (UNEXPECTED(Z_TYPE_P(op1) != IS_STRING)) {
- ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_CONCAT, concat_function);
- use_copy1 = zend_make_printable_zval(op1, &op1_copy TSRMLS_CC);
- if (use_copy1) {
+ do {
+ if (UNEXPECTED(Z_TYPE_P(op1) != IS_STRING)) {
+ ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_CONCAT, concat_function);
+ use_copy1 = 1;
+ op1_str = zval_get_string(op1);
/* We have created a converted copy of op1. Therefore, op1 won't become the result so
* we have to free it.
*/
if (result == op1) {
zval_dtor(op1);
if (UNEXPECTED(op1 == op2)) {
- op2 = &op1_copy;
+ op2_str = op1_str;
+ break;
}
}
- op1 = &op1_copy;
+ } else {
+ op1_str = Z_STR_P(op1);
}
- }
- if (UNEXPECTED(Z_TYPE_P(op2) != IS_STRING)) {
- ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_CONCAT);
- use_copy2 = zend_make_printable_zval(op2, &op2_copy TSRMLS_CC);
- if (use_copy2) {
- op2 = &op2_copy;
+
+ if (UNEXPECTED(Z_TYPE_P(op2) != IS_STRING)) {
+ ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_CONCAT);
+ use_copy2 = 1;
+ op2_str = zval_get_string(op2);
+ } else {
+ op2_str = Z_STR_P(op2);
}
- }
+ } while (0);
{
- size_t op1_len = Z_STRLEN_P(op1);
- size_t op2_len = Z_STRLEN_P(op2);
+ size_t op1_len = op1_str->len;
+ size_t op2_len = op2_str->len;
size_t result_len = op1_len + op2_len;
zend_string *result_str;
@@ -1565,9 +1569,12 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{
if (result == op1 && Z_REFCOUNTED_P(result)) {
/* special case, perform operations on result */
result_str = zend_string_realloc(Z_STR_P(result), result_len, 0);
+ if (UNEXPECTED(op1 == op2)) {
+ op2_str = result_str;
+ }
} else {
result_str = zend_string_alloc(result_len, 0);
- memcpy(result_str->val, Z_STRVAL_P(op1), op1_len);
+ memcpy(result_str->val, op1_str->val, op1_len);
}
/* This has to happen first to account for the cases where result == op1 == op2 and
@@ -1575,15 +1582,15 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{
* point to the new string. The first op2_len bytes of result will still be the same. */
ZVAL_NEW_STR(result, result_str);
- memcpy(result_str->val + op1_len, Z_STRVAL_P(op2), op2_len);
+ memcpy(result_str->val + op1_len, op2_str->val, op2_len);
result_str->val[result_len] = '\0';
}
if (UNEXPECTED(use_copy1)) {
- zval_dtor(op1);
+ zend_string_release(op1_str);
}
if (UNEXPECTED(use_copy2)) {
- zval_dtor(op2);
+ zend_string_release(op2_str);
}
return SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment