--- embedaddon/php/Zend/zend_operators.c 2012/02/21 23:47:52 1.1 +++ embedaddon/php/Zend/zend_operators.c 2014/06/15 20:04:04 1.1.1.4 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2012 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2014 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_operators.c,v 1.1 2012/02/21 23:47:52 misho Exp $ */ +/* $Id: zend_operators.c,v 1.1.1.4 2014/06/15 20:04:04 misho Exp $ */ #include @@ -27,13 +27,10 @@ #include "zend_globals.h" #include "zend_list.h" #include "zend_API.h" -#include "zend_multiply.h" #include "zend_strtod.h" #include "zend_exceptions.h" #include "zend_closures.h" -#define LONG_SIGN_MASK (1L << (8*sizeof(long)-1)) - #if ZEND_USE_TOLOWER_L #include static _locale_t current_locale = NULL; @@ -153,14 +150,9 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS case IS_STRING: { char *strval; - int strl; strval = Z_STRVAL_P(op); - strl = Z_STRLEN_P(op); -#if SUHOSIN_PATCH - Z_STRLEN_P(op) = 0; -#endif - if ((Z_TYPE_P(op)=is_numeric_string(strval, strl, &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) { + if ((Z_TYPE_P(op)=is_numeric_string(strval, Z_STRLEN_P(op), &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) { ZVAL_LONG(op, 0); } STR_FREE(strval); @@ -192,8 +184,7 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS } else { \ switch (Z_TYPE_P(op)) { \ case IS_STRING: \ - { \ - Z_STRLEN(holder) = 0; \ + { \ if ((Z_TYPE(holder)=is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), 1)) == 0) { \ ZVAL_LONG(&(holder), 0); \ } \ @@ -235,7 +226,6 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS Z_LVAL(holder) = zend_dval_to_lval(Z_DVAL_P(op)); \ break; \ case IS_STRING: \ - Z_STRLEN(holder) = 0; \ Z_LVAL(holder) = strtol(Z_STRVAL_P(op), NULL, 10); \ break; \ case IS_ARRAY: \ @@ -278,7 +268,6 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS Z_LVAL(holder) = (Z_DVAL_P(op) ? 1 : 0); \ break; \ case IS_STRING: \ - Z_STRLEN(holder) = 0; \ if (Z_STRLEN_P(op) == 0 \ || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) { \ Z_LVAL(holder) = 0; \ @@ -364,9 +353,6 @@ ZEND_API void convert_to_long_base(zval *op, int base) { char *strval = Z_STRVAL_P(op); -#if SUHOSIN_PATCH - Z_STRLEN_P(op) = 0; -#endif Z_LVAL_P(op) = strtol(strval, NULL, base); STR_FREE(strval); } @@ -427,9 +413,6 @@ ZEND_API void convert_to_double(zval *op) /* {{{ */ { char *strval = Z_STRVAL_P(op); -#if SUHOSIN_PATCH - Z_STRLEN_P(op) = 0; -#endif Z_DVAL_P(op) = zend_strtod(strval, NULL); STR_FREE(strval); } @@ -516,14 +499,8 @@ ZEND_API void convert_to_boolean(zval *op) /* {{{ */ if (Z_STRLEN_P(op) == 0 || (Z_STRLEN_P(op)==1 && Z_STRVAL_P(op)[0]=='0')) { -#if SUHOSIN_PATCH - Z_STRLEN_P(op) = 0; -#endif Z_LVAL_P(op) = 0; } else { -#if SUHOSIN_PATCH - Z_STRLEN_P(op) = 0; -#endif Z_LVAL_P(op) = 1; } STR_FREE(strval); @@ -637,9 +614,6 @@ static void convert_scalar_to_array(zval *op, int type *entry = *op; INIT_PZVAL(entry); -#if SUHOSIN_PATCH - Z_STRLEN_P(op) = 0; -#endif switch (type) { case IS_ARRAY: ALLOC_HASHTABLE(Z_ARRVAL_P(op)); @@ -1222,11 +1196,18 @@ ZEND_API int shift_right_function(zval *result, zval * /* must support result==op1 */ ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */ { - Z_STRLEN_P(result) = Z_STRLEN_P(op1) + 1; - Z_STRVAL_P(result) = (char *) erealloc(Z_STRVAL_P(op1), Z_STRLEN_P(result)+1); - Z_STRVAL_P(result)[Z_STRLEN_P(result) - 1] = (char) Z_LVAL_P(op2); - Z_STRVAL_P(result)[Z_STRLEN_P(result)] = 0; - Z_TYPE_P(result) = IS_STRING; + int length = Z_STRLEN_P(op1) + 1; + char *buf; + + if (IS_INTERNED(Z_STRVAL_P(op1))) { + buf = (char *) emalloc(length + 1); + memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1)); + } else { + buf = (char *) erealloc(Z_STRVAL_P(op1), length + 1); + } + buf[length - 1] = (char) Z_LVAL_P(op2); + buf[length] = 0; + ZVAL_STRINGL(result, buf, length, 0); return SUCCESS; } /* }}} */ @@ -1235,12 +1216,17 @@ ZEND_API int add_char_to_string(zval *result, const zv ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */ { int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2); + char *buf; - Z_STRVAL_P(result) = (char *) erealloc(Z_STRVAL_P(op1), length+1); - memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2)); - Z_STRVAL_P(result)[length] = 0; - Z_STRLEN_P(result) = length; - Z_TYPE_P(result) = IS_STRING; + if (IS_INTERNED(Z_STRVAL_P(op1))) { + buf = (char *) emalloc(length+1); + memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1)); + } else { + buf = (char *) erealloc(Z_STRVAL_P(op1), length+1); + } + memcpy(buf + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2)); + buf[length] = 0; + ZVAL_STRINGL(result, buf, length, 0); return SUCCESS; } /* }}} */ @@ -1269,7 +1255,7 @@ ZEND_API int concat_function(zval *result, zval *op1, if (use_copy2) { op2 = &op2_copy; } - if (result==op1) { /* special case, perform operations on result */ + if (result==op1 && !IS_INTERNED(Z_STRVAL_P(op1))) { /* special case, perform operations on result */ uint res_len = Z_STRLEN_P(op1) + Z_STRLEN_P(op2); if (Z_STRLEN_P(result) < 0 || (int) (Z_STRLEN_P(op1) + Z_STRLEN_P(op2)) < 0) { @@ -1284,12 +1270,13 @@ ZEND_API int concat_function(zval *result, zval *op1, Z_STRVAL_P(result)[res_len]=0; Z_STRLEN_P(result) = res_len; } else { - Z_STRLEN_P(result) = Z_STRLEN_P(op1) + Z_STRLEN_P(op2); - Z_STRVAL_P(result) = (char *) emalloc(Z_STRLEN_P(result) + 1); - memcpy(Z_STRVAL_P(result), Z_STRVAL_P(op1), Z_STRLEN_P(op1)); - memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2)); - Z_STRVAL_P(result)[Z_STRLEN_P(result)] = 0; - Z_TYPE_P(result) = IS_STRING; + int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2); + char *buf = (char *) emalloc(length + 1); + + memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1)); + memcpy(buf + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2)); + buf[length] = 0; + ZVAL_STRINGL(result, buf, length, 0); } if (use_copy1) { zval_dtor(op1); @@ -1301,7 +1288,7 @@ ZEND_API int concat_function(zval *result, zval *op1, } /* }}} */ -ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ +ZEND_API int string_compare_function_ex(zval *result, zval *op1, zval *op2, zend_bool case_insensitive TSRMLS_DC) /* {{{ */ { zval op1_copy, op2_copy; int use_copy1 = 0, use_copy2 = 0; @@ -1320,7 +1307,11 @@ ZEND_API int string_compare_function(zval *result, zva op2 = &op2_copy; } - ZVAL_LONG(result, zend_binary_zval_strcmp(op1, op2)); + if (case_insensitive) { + ZVAL_LONG(result, zend_binary_zval_strcasecmp(op1, op2)); + } else { + ZVAL_LONG(result, zend_binary_zval_strcmp(op1, op2)); + } if (use_copy1) { zval_dtor(op1); @@ -1332,6 +1323,18 @@ ZEND_API int string_compare_function(zval *result, zva } /* }}} */ +ZEND_API int string_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ +{ + return string_compare_function_ex(result, op1, op2, 0 TSRMLS_CC); +} +/* }}} */ + +ZEND_API int string_case_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ +{ + return string_compare_function_ex(result, op1, op2, 1 TSRMLS_CC); +} +/* }}} */ + #if HAVE_STRCOLL ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ { @@ -1420,8 +1423,12 @@ ZEND_API int compare_function(zval *result, zval *op1, return SUCCESS; case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE): - Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2); - ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result))); + if (Z_DVAL_P(op1) == Z_DVAL_P(op2)) { + ZVAL_LONG(result, 0); + } else { + Z_DVAL_P(result) = Z_DVAL_P(op1) - Z_DVAL_P(op2); + ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_DVAL_P(result))); + } return SUCCESS; case TYPE_PAIR(IS_ARRAY, IS_ARRAY): @@ -1468,7 +1475,7 @@ ZEND_API int compare_function(zval *result, zval *op1, /* If both are objects sharing the same comparision handler then use is */ if (Z_OBJ_HANDLER_P(op1,compare_objects) == Z_OBJ_HANDLER_P(op2,compare_objects)) { if (Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2)) { - /* object handles are identical, apprently this is the same object */ + /* object handles are identical, apparently this is the same object */ ZVAL_LONG(result, 0); return SUCCESS; } @@ -1512,6 +1519,9 @@ ZEND_API int compare_function(zval *result, zval *op1, ret = compare_function(result, op1, op_free TSRMLS_CC); zend_free_obj_get_result(op_free TSRMLS_CC); return ret; + } else if (Z_TYPE_P(op1) == IS_OBJECT) { + ZVAL_LONG(result, 1); + return SUCCESS; } } if (!converted) { @@ -1598,7 +1608,8 @@ ZEND_API int is_identical_function(zval *result, zval && (!memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1)))); break; case IS_ARRAY: - Z_LVAL_P(result) = zend_hash_compare(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2), (compare_func_t) hash_zval_identical_function, 1 TSRMLS_CC)==0; + Z_LVAL_P(result) = (Z_ARRVAL_P(op1) == Z_ARRVAL_P(op2) || + zend_hash_compare(Z_ARRVAL_P(op1), Z_ARRVAL_P(op2), (compare_func_t) hash_zval_identical_function, 1 TSRMLS_CC)==0); break; case IS_OBJECT: if (Z_OBJ_HT_P(op1) == Z_OBJ_HT_P(op2)) { @@ -1713,6 +1724,12 @@ static void increment_string(zval *str) /* {{{ */ return; } + if (IS_INTERNED(s)) { + s = (char*) emalloc(Z_STRLEN_P(str) + 1); + memcpy(s, Z_STRVAL_P(str), Z_STRLEN_P(str) + 1); + Z_STRVAL_P(str) = s; + } + while (pos >= 0) { ch = s[pos]; if (ch >= 'a' && ch <= 'z') { @@ -1798,7 +1815,7 @@ ZEND_API int increment_function(zval *op1) /* {{{ */ switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) { case IS_LONG: - efree(Z_STRVAL_P(op1)); + str_efree(Z_STRVAL_P(op1)); if (lval == LONG_MAX) { /* switch to double */ double d = (double)lval; @@ -1808,7 +1825,7 @@ ZEND_API int increment_function(zval *op1) /* {{{ */ } break; case IS_DOUBLE: - efree(Z_STRVAL_P(op1)); + str_efree(Z_STRVAL_P(op1)); ZVAL_DOUBLE(op1, dval+1); break; default: @@ -1924,6 +1941,9 @@ ZEND_API int zend_binary_strcmp(const char *s1, uint l { int retval; + if (s1 == s2) { + return 0; + } retval = memcmp(s1, s2, MIN(len1, len2)); if (!retval) { return (len1 - len2); @@ -1937,6 +1957,9 @@ ZEND_API int zend_binary_strncmp(const char *s1, uint { int retval; + if (s1 == s2) { + return 0; + } retval = memcmp(s1, s2, MIN(length, MIN(len1, len2))); if (!retval) { return (MIN(length, len1) - MIN(length, len2)); @@ -1951,8 +1974,11 @@ ZEND_API int zend_binary_strcasecmp(const char *s1, ui int len; int c1, c2; - len = MIN(len1, len2); + if (s1 == s2) { + return 0; + } + len = MIN(len1, len2); while (len--) { c1 = zend_tolower((int)*(unsigned char *)s1++); c2 = zend_tolower((int)*(unsigned char *)s2++); @@ -1970,8 +1996,10 @@ ZEND_API int zend_binary_strncasecmp(const char *s1, u int len; int c1, c2; + if (s1 == s2) { + return 0; + } len = MIN(length, MIN(len1, len2)); - while (len--) { c1 = zend_tolower((int)*(unsigned char *)s1++); c2 = zend_tolower((int)*(unsigned char *)s2++); @@ -2011,15 +2039,36 @@ ZEND_API int zend_binary_zval_strncasecmp(zval *s1, zv ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2) /* {{{ */ { int ret1, ret2; + int oflow1, oflow2; long lval1, lval2; double dval1, dval2; - if ((ret1=is_numeric_string(Z_STRVAL_P(s1), Z_STRLEN_P(s1), &lval1, &dval1, 0)) && - (ret2=is_numeric_string(Z_STRVAL_P(s2), Z_STRLEN_P(s2), &lval2, &dval2, 0))) { + if ((ret1=is_numeric_string_ex(Z_STRVAL_P(s1), Z_STRLEN_P(s1), &lval1, &dval1, 0, &oflow1)) && + (ret2=is_numeric_string_ex(Z_STRVAL_P(s2), Z_STRLEN_P(s2), &lval2, &dval2, 0, &oflow2))) { +#if ULONG_MAX == 0xFFFFFFFF + if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0. && + ((oflow1 == 1 && dval1 > 9007199254740991. /*0x1FFFFFFFFFFFFF*/) + || (oflow1 == -1 && dval1 < -9007199254740991.))) { +#else + if (oflow1 != 0 && oflow1 == oflow2 && dval1 - dval2 == 0.) { +#endif + /* both values are integers overflown to the same side, and the + * double comparison may have resulted in crucial accuracy lost */ + goto string_cmp; + } if ((ret1==IS_DOUBLE) || (ret2==IS_DOUBLE)) { if (ret1!=IS_DOUBLE) { + if (oflow2) { + /* 2nd operand is integer > LONG_MAX (oflow2==1) or < LONG_MIN (-1) */ + ZVAL_LONG(result, -1 * oflow2); + return; + } dval1 = (double) lval1; } else if (ret2!=IS_DOUBLE) { + if (oflow1) { + ZVAL_LONG(result, oflow1); + return; + } dval2 = (double) lval2; } else if (dval1 == dval2 && !zend_finite(dval1)) { /* Both values overflowed and have the same sign, @@ -2052,13 +2101,13 @@ static int hash_zval_compare_function(const zval **z1, ZEND_API int zend_compare_symbol_tables_i(HashTable *ht1, HashTable *ht2 TSRMLS_DC) /* {{{ */ { - return zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC); + return ht1 == ht2 ? 0 : zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC); } /* }}} */ ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2 TSRMLS_DC) /* {{{ */ { - ZVAL_LONG(result, zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC)); + ZVAL_LONG(result, ht1 == ht2 ? 0 : zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC)); } /* }}} */