|
|
|
@ -297,38 +297,36 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV) |
|
|
|
zend_string *op2_str = Z_STR_P(op2); |
|
|
|
zend_string *str; |
|
|
|
|
|
|
|
do { |
|
|
|
if (OP1_TYPE != IS_CONST) { |
|
|
|
if (UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { |
|
|
|
ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); |
|
|
|
FREE_OP1(); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
if (OP2_TYPE != IS_CONST) { |
|
|
|
if (UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { |
|
|
|
ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); |
|
|
|
FREE_OP1(); |
|
|
|
break; |
|
|
|
} |
|
|
|
if (OP1_TYPE != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { |
|
|
|
if (OP2_TYPE == IS_CONST || OP2_TYPE == IS_CV) { |
|
|
|
ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); |
|
|
|
} else { |
|
|
|
ZVAL_STR(EX_VAR(opline->result.var), op2_str); |
|
|
|
} |
|
|
|
if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_CV && |
|
|
|
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { |
|
|
|
size_t len = ZSTR_LEN(op1_str); |
|
|
|
|
|
|
|
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); |
|
|
|
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); |
|
|
|
ZVAL_NEW_STR(EX_VAR(opline->result.var), str); |
|
|
|
break; |
|
|
|
FREE_OP1(); |
|
|
|
} else if (OP2_TYPE != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { |
|
|
|
if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_CV) { |
|
|
|
ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); |
|
|
|
} else { |
|
|
|
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); |
|
|
|
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); |
|
|
|
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); |
|
|
|
ZVAL_NEW_STR(EX_VAR(opline->result.var), str); |
|
|
|
ZVAL_STR(EX_VAR(opline->result.var), op1_str); |
|
|
|
} |
|
|
|
FREE_OP2(); |
|
|
|
} else if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_CV && |
|
|
|
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { |
|
|
|
size_t len = ZSTR_LEN(op1_str); |
|
|
|
|
|
|
|
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); |
|
|
|
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); |
|
|
|
ZVAL_NEW_STR(EX_VAR(opline->result.var), str); |
|
|
|
FREE_OP2(); |
|
|
|
} else { |
|
|
|
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); |
|
|
|
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); |
|
|
|
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); |
|
|
|
ZVAL_NEW_STR(EX_VAR(opline->result.var), str); |
|
|
|
FREE_OP1(); |
|
|
|
} while (0); |
|
|
|
FREE_OP2(); |
|
|
|
FREE_OP2(); |
|
|
|
} |
|
|
|
ZEND_VM_NEXT_OPCODE(); |
|
|
|
} else { |
|
|
|
SAVE_OPLINE(); |
|
|
|
@ -2734,38 +2732,36 @@ ZEND_VM_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV) |
|
|
|
zend_string *op2_str = Z_STR_P(op2); |
|
|
|
zend_string *str; |
|
|
|
|
|
|
|
do { |
|
|
|
if (OP1_TYPE != IS_CONST) { |
|
|
|
if (UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { |
|
|
|
ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); |
|
|
|
FREE_OP1(); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
if (OP2_TYPE != IS_CONST) { |
|
|
|
if (UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { |
|
|
|
ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); |
|
|
|
FREE_OP1(); |
|
|
|
break; |
|
|
|
} |
|
|
|
if (OP1_TYPE != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { |
|
|
|
if (OP2_TYPE == IS_CONST || OP2_TYPE == IS_CV) { |
|
|
|
ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); |
|
|
|
} else { |
|
|
|
ZVAL_STR(EX_VAR(opline->result.var), op2_str); |
|
|
|
} |
|
|
|
if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_CV && |
|
|
|
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { |
|
|
|
size_t len = ZSTR_LEN(op1_str); |
|
|
|
|
|
|
|
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); |
|
|
|
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); |
|
|
|
ZVAL_NEW_STR(EX_VAR(opline->result.var), str); |
|
|
|
break; |
|
|
|
FREE_OP1(); |
|
|
|
} else if (OP2_TYPE != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { |
|
|
|
if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_CV) { |
|
|
|
ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); |
|
|
|
} else { |
|
|
|
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); |
|
|
|
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); |
|
|
|
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); |
|
|
|
ZVAL_NEW_STR(EX_VAR(opline->result.var), str); |
|
|
|
ZVAL_STR(EX_VAR(opline->result.var), op1_str); |
|
|
|
} |
|
|
|
FREE_OP2(); |
|
|
|
} else if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_CV && |
|
|
|
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { |
|
|
|
size_t len = ZSTR_LEN(op1_str); |
|
|
|
|
|
|
|
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); |
|
|
|
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); |
|
|
|
ZVAL_NEW_STR(EX_VAR(opline->result.var), str); |
|
|
|
FREE_OP2(); |
|
|
|
} else { |
|
|
|
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); |
|
|
|
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); |
|
|
|
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); |
|
|
|
ZVAL_NEW_STR(EX_VAR(opline->result.var), str); |
|
|
|
FREE_OP1(); |
|
|
|
} while (0); |
|
|
|
FREE_OP2(); |
|
|
|
FREE_OP2(); |
|
|
|
} |
|
|
|
ZEND_VM_NEXT_OPCODE(); |
|
|
|
} |
|
|
|
|
|
|
|
|