Index: Zend/zend_operators.c =================================================================== RCS file: /repository/ZendEngine2/zend_operators.c,v retrieving revision 1.208.2.4.2.23.2.22 diff -u -r1.208.2.4.2.23.2.22 zend_operators.c --- Zend/zend_operators.c 18 Mar 2009 11:25:37 -0000 1.208.2.4.2.23.2.22 +++ Zend/zend_operators.c 19 Mar 2009 00:26:52 -0000 @@ -44,6 +44,15 @@ #define TYPE_PAIR(t1,t2) (((t1) << 4) | (t2)) +#define ZVAL_LONG64_SET(z, value) { \ + zend_long64 __result = (zend_long64) (value); \ + if (__result > LONG_MAX || __result < LONG_MIN) { \ + ZVAL_DOUBLE(z, (double) __result); \ + } else { \ + ZVAL_LONG(z, (long) __result); \ + } \ + } + ZEND_API int zend_atoi(const char *str, int str_len) { int retval; @@ -247,6 +256,42 @@ } +#define zendi_convert_to_double(op, holder, result) \ + if (Z_TYPE_P(op) != IS_DOUBLE) { \ + if (op == result) { \ + convert_to_double(op); \ + } else { \ + switch (Z_TYPE_P(op)) { \ + case IS_NULL: \ + Z_DVAL(holder) = 0; \ + break; \ + case IS_BOOL: \ + case IS_LONG: \ + case IS_RESOURCE: \ + Z_DVAL(holder) = (double) Z_LVAL_P(op); \ + break; \ + case IS_STRING: \ + Z_DVAL(holder) = zend_strtod(Z_STRVAL_P(op), NULL); \ + break; \ + case IS_ARRAY: \ + Z_DVAL(holder) = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0); \ + break; \ + case IS_OBJECT: \ + (holder) = (*(op)); \ + zval_copy_ctor(&(holder)); \ + convert_to_double(&(holder)); \ + break; \ + default: \ + zend_error(E_WARNING, "Cannot convert to real value (type=%d)", Z_TYPE_P(op)); \ + Z_DVAL(holder) = 0; \ + break; \ + } \ + Z_TYPE(holder) = IS_DOUBLE; \ + (op) = &(holder); \ + } \ + } + + #define zendi_convert_to_boolean(op, holder, result) \ if (op==result) { \ convert_to_boolean(op); \ @@ -957,8 +1002,34 @@ { zval op1_copy, op2_copy; +#if SIZEOF_LONG == 4 && defined(HAVE_ZEND_LONG64) + if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) { + zend_long64 op2_64; + + zendi_convert_to_double(op1, op1_copy, result); + zendi_convert_to_double(op2, op2_copy, result); + + op2_64 = (zend_long64) Z_DVAL_P(op2); + + if (op2_64 == 0) { + zend_error(E_WARNING, "Division by zero"); + ZVAL_BOOL(result, 0); + return FAILURE; /* modulus by zero */ + } + + if (op2_64 == -1) { + /* Prevent overflow error/crash if op1==-2^63 */ + ZVAL_LONG(result, 0); + return SUCCESS; + } + + ZVAL_LONG64_SET(result, (zend_long64) Z_DVAL_P(op1) % op2_64); + return SUCCESS; + } +#else zendi_convert_to_long(op1, op1_copy, result); zendi_convert_to_long(op2, op2_copy, result); +#endif if (Z_LVAL_P(op2) == 0) { zend_error(E_WARNING, "Division by zero"); @@ -1002,18 +1073,21 @@ ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC) { - zval op1_copy = *op1; - - op1 = &op1_copy; - if (Z_TYPE_P(op1) == IS_LONG) { ZVAL_LONG(result, ~Z_LVAL_P(op1)); return SUCCESS; } else if (Z_TYPE_P(op1) == IS_DOUBLE) { +#if SIZEOF_LONG == 4 && defined(HAVE_ZEND_LONG64) + ZVAL_LONG64_SET(result, ~(zend_long64) Z_DVAL_P(op1)); +#else ZVAL_LONG(result, ~(long) Z_DVAL_P(op1)); +#endif return SUCCESS; } else if (Z_TYPE_P(op1) == IS_STRING) { int i; + zval op1_copy = *op1; + + op1 = &op1_copy; Z_TYPE_P(result) = IS_STRING; Z_STRVAL_P(result) = estrndup(Z_STRVAL_P(op1), Z_STRLEN_P(op1)); @@ -1058,8 +1132,19 @@ Z_STRLEN_P(result) = result_len; return SUCCESS; } + +#if SIZEOF_LONG == 4 && defined(HAVE_ZEND_LONG64) + if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) { + zendi_convert_to_double(op1, op1_copy, result); + zendi_convert_to_double(op2, op2_copy, result); + + ZVAL_LONG64_SET(result, (zend_long64) Z_DVAL_P(op1) | (zend_long64) Z_DVAL_P(op2)); + return SUCCESS; + } +#else zendi_convert_to_long(op1, op1_copy, result); zendi_convert_to_long(op2, op2_copy, result); +#endif ZVAL_LONG(result, Z_LVAL_P(op1) | Z_LVAL_P(op2)); return SUCCESS; @@ -1097,9 +1182,18 @@ return SUCCESS; } +#if SIZEOF_LONG == 4 && defined(HAVE_ZEND_LONG64) + if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) { + zendi_convert_to_double(op1, op1_copy, result); + zendi_convert_to_double(op2, op2_copy, result); + ZVAL_LONG64_SET(result, (zend_long64) Z_DVAL_P(op1) & (zend_long64) Z_DVAL_P(op2)); + return SUCCESS; + } +#else zendi_convert_to_long(op1, op1_copy, result); zendi_convert_to_long(op2, op2_copy, result); +#endif ZVAL_LONG(result, Z_LVAL_P(op1) & Z_LVAL_P(op2)); return SUCCESS; @@ -1137,8 +1231,18 @@ return SUCCESS; } +#if SIZEOF_LONG == 4 && defined(HAVE_ZEND_LONG64) + if (Z_TYPE_P(op1) != IS_LONG || Z_TYPE_P(op2) != IS_LONG) { + zendi_convert_to_double(op1, op1_copy, result); + zendi_convert_to_double(op2, op2_copy, result); + + ZVAL_LONG64_SET(result, (zend_long64) Z_DVAL_P(op1) ^ (zend_long64) Z_DVAL_P(op2)); + return SUCCESS; + } +#else zendi_convert_to_long(op1, op1_copy, result); zendi_convert_to_long(op2, op2_copy, result); +#endif ZVAL_LONG(result, Z_LVAL_P(op1) ^ Z_LVAL_P(op2)); return SUCCESS; @@ -1149,9 +1253,19 @@ { zval op1_copy, op2_copy; - zendi_convert_to_long(op1, op1_copy, result); zendi_convert_to_long(op2, op2_copy, result); + +#if SIZEOF_LONG == 4 && defined(HAVE_ZEND_LONG64) + if (Z_TYPE_P(op1) != IS_LONG) { + zendi_convert_to_double(op1, op1_copy, result); + ZVAL_LONG64_SET(result, (zend_long64) Z_DVAL_P(op1) << Z_LVAL_P(op2)); + } else { + ZVAL_LONG64_SET(result, (zend_long64) Z_LVAL_P(op1) << Z_LVAL_P(op2)); + } +#else + zendi_convert_to_long(op1, op1_copy, result); ZVAL_LONG(result, Z_LVAL_P(op1) << Z_LVAL_P(op2)); +#endif return SUCCESS; } @@ -1160,8 +1274,17 @@ { zval op1_copy, op2_copy; - zendi_convert_to_long(op1, op1_copy, result); zendi_convert_to_long(op2, op2_copy, result); + +#if SIZEOF_LONG == 4 && defined(HAVE_ZEND_LONG64) + if (Z_TYPE_P(op1) != IS_LONG) { + zendi_convert_to_double(op1, op1_copy, result); + ZVAL_LONG64_SET(result, (zend_long64) Z_DVAL_P(op1) >> Z_LVAL_P(op2)); + return SUCCESS; + } +#else + zendi_convert_to_long(op1, op1_copy, result); +#endif ZVAL_LONG(result, Z_LVAL_P(op1) >> Z_LVAL_P(op2)); return SUCCESS; } Index: NEWS =================================================================== RCS file: /repository/php-src/NEWS,v retrieving revision 1.2027.2.547.2.965.2.524 diff -u -r1.2027.2.547.2.965.2.524 NEWS --- NEWS 18 Mar 2009 17:48:18 -0000 1.2027.2.547.2.965.2.524 +++ NEWS 19 Mar 2009 00:27:06 -0000 @@ -6,6 +6,9 @@ - Re-enabled phar for big-endian systems after fixing problems. (Greg) +- Extended range of bitwise and modulus operators on 32-bit platforms that have + a 64-bit integer type available. (Matt) + - Added LIBXML_LOADED_VERSION constant (libxml2 version currently used). (Rob) - Added JSON_FORCE_OBJECT flag to json_encode(). (Scott, Richard Quadling)