mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Fix fallback paths in fast_long_{add,sub}_function
This was asked to be checked in https://github.com/php/php-src/pull/17472#issuecomment-2591325036 There are 2 issues: 1) The UB in the if can overflow, and can be fixed by using zend_ulong for the sum/sub. 2) fast_long_sub_function() has a problem when result aliases. This is fixed in the same way as fast_long_add_function() works. Closes GH-17666.
This commit is contained in:
1
NEWS
1
NEWS
@@ -10,6 +10,7 @@ PHP NEWS
|
||||
compilation). (ilutov)
|
||||
. Fixed bug GH-17618 (UnhandledMatchError does not take
|
||||
zend.exception_ignore_args=1 into account). (timwolla)
|
||||
. Fix fallback paths in fast_long_{add,sub}_function. (nielsdos)
|
||||
|
||||
- Opcache:
|
||||
. Fixed bug GH-17654 (Multiple classes using same trait causes function
|
||||
|
||||
@@ -722,11 +722,13 @@ overflow: ZEND_ATTRIBUTE_COLD_LABEL
|
||||
* have read the values of op1 and op2.
|
||||
*/
|
||||
|
||||
zend_long sum = (zend_long) ((zend_ulong) Z_LVAL_P(op1) + (zend_ulong) Z_LVAL_P(op2));
|
||||
|
||||
if (UNEXPECTED((Z_LVAL_P(op1) & LONG_SIGN_MASK) == (Z_LVAL_P(op2) & LONG_SIGN_MASK)
|
||||
&& (Z_LVAL_P(op1) & LONG_SIGN_MASK) != ((Z_LVAL_P(op1) + Z_LVAL_P(op2)) & LONG_SIGN_MASK))) {
|
||||
&& (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (sum & LONG_SIGN_MASK))) {
|
||||
ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) + (double) Z_LVAL_P(op2));
|
||||
} else {
|
||||
ZVAL_LONG(result, Z_LVAL_P(op1) + Z_LVAL_P(op2));
|
||||
ZVAL_LONG(result, sum);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -804,11 +806,19 @@ overflow: ZEND_ATTRIBUTE_COLD_LABEL
|
||||
ZVAL_LONG(result, llresult);
|
||||
}
|
||||
#else
|
||||
ZVAL_LONG(result, Z_LVAL_P(op1) - Z_LVAL_P(op2));
|
||||
/*
|
||||
* 'result' may alias with op1 or op2, so we need to
|
||||
* ensure that 'result' is not updated until after we
|
||||
* have read the values of op1 and op2.
|
||||
*/
|
||||
|
||||
zend_long sub = (zend_long) ((zend_ulong) Z_LVAL_P(op1) - (zend_ulong) Z_LVAL_P(op2));
|
||||
|
||||
if (UNEXPECTED((Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(op2) & LONG_SIGN_MASK)
|
||||
&& (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (Z_LVAL_P(result) & LONG_SIGN_MASK))) {
|
||||
&& (Z_LVAL_P(op1) & LONG_SIGN_MASK) != (sub & LONG_SIGN_MASK))) {
|
||||
ZVAL_DOUBLE(result, (double) Z_LVAL_P(op1) - (double) Z_LVAL_P(op2));
|
||||
} else {
|
||||
ZVAL_LONG(result, sub);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user