Commit 4737de1f authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Commit Bot

[ubsan] Fix "division by zero" UBSan reports

The C++ spec does not guarantee IEEE-754 behavior for doubles, in
particular it says that dividing by zero is undefined behavior,
and UBSan complains about it when it happens.

Bug: v8:3770
Change-Id: I79e52c0e11ebfb581191f6f1c3ff95eb747dd97f
Reviewed-on: https://chromium-review.googlesource.com/c/1391751
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58580}
parent 753ff7f3
......@@ -998,7 +998,7 @@ double acosh(double x) {
uint32_t lx;
EXTRACT_WORDS(hx, lx, x);
if (hx < 0x3FF00000) { /* x < 1 */
return (x - x) / (x - x);
return divide(x - x, x - x);
} else if (hx >= 0x41B00000) { /* x > 2**28 */
if (hx >= 0x7FF00000) { /* x is inf of NaN */
return x + x;
......@@ -1431,6 +1431,18 @@ double cos(double x) {
}
}
/* div(x, y)
* Returns the quotient x/y, avoiding C++ undefined behavior if y == 0.
*/
double divide(double x, double y) {
if (y != 0) return x / y;
if (x == 0) return std::numeric_limits<double>::quiet_NaN();
if ((x > 0) == (bit_cast<uint64_t>(y) == 0)) {
return std::numeric_limits<double>::infinity();
}
return -std::numeric_limits<double>::infinity();
}
/* exp(x)
* Returns the exponential of x.
*
......
......@@ -36,6 +36,9 @@ V8_BASE_EXPORT double atan2(double y, double x);
// Returns the cosine of |x|, where |x| is given in radians.
V8_BASE_EXPORT double cos(double x);
// Returns the quotient of x and y, avoiding C++ undefined behavior if y == 0.
V8_BASE_EXPORT double divide(double x, double y);
// Returns the base-e exponential of |x|.
V8_BASE_EXPORT double exp(double x);
......
......@@ -12,6 +12,7 @@
#include "src/ast/ast.h"
#include "src/ast/source-range-ast-visitor.h"
#include "src/bailout-reason.h"
#include "src/base/ieee754.h"
#include "src/base/platform/platform.h"
#include "src/char-predicates-inl.h"
#include "src/compiler-dispatcher/compiler-dispatcher.h"
......@@ -159,7 +160,8 @@ bool Parser::ShortcutNumericLiteralBinaryExpression(Expression** x,
*x = factory()->NewNumberLiteral(x_val * y_val, pos);
return true;
case Token::DIV:
*x = factory()->NewNumberLiteral(x_val / y_val, pos);
*x = factory()->NewNumberLiteral(base::ieee754::divide(x_val, y_val),
pos);
return true;
case Token::BIT_OR: {
int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment