mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Commit 64-bit fixes to the standard operators
by Ard Biesheuvel (abies@php.net)
This commit is contained in:
parent
a5d829f928
commit
e0508c13bb
1 changed files with 22 additions and 13 deletions
|
@ -33,6 +33,8 @@
|
||||||
#include "ext/bcmath/number.h"
|
#include "ext/bcmath/number.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define LONG_SIGN_MASK (1L << (8*SIZEOF_LONG-1))
|
||||||
|
|
||||||
ZEND_API int zend_atoi(const char *str, int str_len)
|
ZEND_API int zend_atoi(const char *str, int str_len)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
@ -664,13 +666,16 @@ ZEND_API int add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
|
||||||
|
|
||||||
|
|
||||||
if (op1->type == IS_LONG && op2->type == IS_LONG) {
|
if (op1->type == IS_LONG && op2->type == IS_LONG) {
|
||||||
double dval = (double) op1->value.lval + (double) op2->value.lval;
|
long lval = op1->value.lval + op2->value.lval;
|
||||||
|
|
||||||
|
/* check for overflow by comparing sign bits */
|
||||||
|
if ( (op1->value.lval & LONG_SIGN_MASK) == (op2->value.lval & LONG_SIGN_MASK)
|
||||||
|
&& (op1->value.lval & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
|
||||||
|
|
||||||
if ((dval > (double) LONG_MAX) || (dval < (double) LONG_MIN)) {
|
result->value.dval = (double) op1->value.lval + (double) op2->value.lval;
|
||||||
result->value.dval = dval;
|
|
||||||
result->type = IS_DOUBLE;
|
result->type = IS_DOUBLE;
|
||||||
} else {
|
} else {
|
||||||
result->value.lval = op1->value.lval + op2->value.lval;
|
result->value.lval = lval;
|
||||||
result->type = IS_LONG;
|
result->type = IS_LONG;
|
||||||
}
|
}
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
|
@ -701,13 +706,16 @@ ZEND_API int sub_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
|
||||||
zendi_convert_scalar_to_number(op2, op2_copy, result);
|
zendi_convert_scalar_to_number(op2, op2_copy, result);
|
||||||
|
|
||||||
if (op1->type == IS_LONG && op2->type == IS_LONG) {
|
if (op1->type == IS_LONG && op2->type == IS_LONG) {
|
||||||
double dval = (double) op1->value.lval - (double) op2->value.lval;
|
long lval = op1->value.lval - op2->value.lval;
|
||||||
|
|
||||||
|
/* check for overflow by comparing sign bits */
|
||||||
|
if ( (op1->value.lval & LONG_SIGN_MASK) != (op2->value.lval & LONG_SIGN_MASK)
|
||||||
|
&& (op1->value.lval & LONG_SIGN_MASK) != (lval & LONG_SIGN_MASK)) {
|
||||||
|
|
||||||
if ((dval < (double) LONG_MIN) || (dval > (double) LONG_MAX)) {
|
result->value.dval = (double) op1->value.lval - (double) op2->value.lval;
|
||||||
result->value.dval = dval;
|
|
||||||
result->type = IS_DOUBLE;
|
result->type = IS_DOUBLE;
|
||||||
} else {
|
} else {
|
||||||
result->value.lval = op1->value.lval - op2->value.lval;
|
result->value.lval = lval;
|
||||||
result->type = IS_LONG;
|
result->type = IS_LONG;
|
||||||
}
|
}
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
|
@ -738,13 +746,14 @@ ZEND_API int mul_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
|
||||||
zendi_convert_scalar_to_number(op2, op2_copy, result);
|
zendi_convert_scalar_to_number(op2, op2_copy, result);
|
||||||
|
|
||||||
if (op1->type == IS_LONG && op2->type == IS_LONG) {
|
if (op1->type == IS_LONG && op2->type == IS_LONG) {
|
||||||
double dval = (double) op1->value.lval * (double) op2->value.lval;
|
long lval = op1->value.lval * op2->value.lval;
|
||||||
|
|
||||||
if ((dval > (double) LONG_MAX) || (dval < (double) LONG_MIN)) {
|
/* check for overflow by applying the reverse calculation */
|
||||||
result->value.dval = dval;
|
if (op1->value.lval != 0 && lval / op1->value.lval != op2->value.lval) {
|
||||||
|
result->value.dval = (double) op1->value.lval * (double) op2->value.lval;
|
||||||
result->type = IS_DOUBLE;
|
result->type = IS_DOUBLE;
|
||||||
} else {
|
} else {
|
||||||
result->value.lval = op1->value.lval * op2->value.lval;
|
result->value.lval = lval;
|
||||||
result->type = IS_LONG;
|
result->type = IS_LONG;
|
||||||
}
|
}
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue