diff options
author | JF Bastien <jfb@chromium.org> | 2016-03-28 12:52:56 -0700 |
---|---|---|
committer | JF Bastien <jfb@chromium.org> | 2016-03-28 12:52:56 -0700 |
commit | e34634c2448d0de88284ec01356e8cb98af54ada (patch) | |
tree | 2fa2e2d23ebc062d7d848e877316ddeb8583a61f /src/support/safe_integer.cpp | |
parent | b8d01b47e5f53a92cd5db528d1939462f919d5f6 (diff) | |
download | binaryen-e34634c2448d0de88284ec01356e8cb98af54ada.tar.gz binaryen-e34634c2448d0de88284ec01356e8cb98af54ada.tar.bz2 binaryen-e34634c2448d0de88284ec01356e8cb98af54ada.zip |
Tighten safe integer
#282 removed the assert, but the code didn't handle negative -> unsigned conversion properly, and doesn't behave well with -0.0. I'm not super comfortable with 64-bit int min / max to double conversions either, but that'll be for another patch.
Diffstat (limited to 'src/support/safe_integer.cpp')
-rw-r--r-- | src/support/safe_integer.cpp | 34 |
1 files changed, 18 insertions, 16 deletions
diff --git a/src/support/safe_integer.cpp b/src/support/safe_integer.cpp index 191296e1e..bce2cbc39 100644 --- a/src/support/safe_integer.cpp +++ b/src/support/safe_integer.cpp @@ -25,7 +25,8 @@ using namespace wasm; bool wasm::isInteger(double x) { return fmod(x, 1) == 0; } bool wasm::isUInteger32(double x) { - return isInteger(x) && x >= 0 && x <= std::numeric_limits<uint32_t>::max(); + return !std::signbit(x) && isInteger(x) && + x <= std::numeric_limits<uint32_t>::max(); } bool wasm::isSInteger32(double x) { @@ -34,21 +35,22 @@ bool wasm::isSInteger32(double x) { } uint32_t wasm::toUInteger32(double x) { - return x < std::numeric_limits<uint32_t>::max() - ? x - : std::numeric_limits<uint32_t>::max(); + return std::signbit(x) ? 0 : (x < std::numeric_limits<uint32_t>::max() + ? x + : std::numeric_limits<uint32_t>::max()); } int32_t wasm::toSInteger32(double x) { - return x > std::numeric_limits<int32_t>::min() && - x < std::numeric_limits<int32_t>::max() + return (x > std::numeric_limits<int32_t>::min() && + x < std::numeric_limits<int32_t>::max()) ? x - : (x < 0 ? std::numeric_limits<int32_t>::min() - : std::numeric_limits<int32_t>::max()); + : (std::signbit(x) ? std::numeric_limits<int32_t>::min() + : std::numeric_limits<int32_t>::max()); } bool wasm::isUInteger64(double x) { - return isInteger(x) && x >= 0 && x <= std::numeric_limits<uint64_t>::max(); + return !std::signbit(x) && isInteger(x) && + x <= std::numeric_limits<uint64_t>::max(); } bool wasm::isSInteger64(double x) { @@ -57,15 +59,15 @@ bool wasm::isSInteger64(double x) { } uint64_t wasm::toUInteger64(double x) { - return x < (double)std::numeric_limits<uint64_t>::max() - ? (uint64_t)x - : std::numeric_limits<uint64_t>::max(); + return std::signbit(x) ? 0 : (x < (double)std::numeric_limits<uint64_t>::max() + ? (uint64_t)x + : std::numeric_limits<uint64_t>::max()); } int64_t wasm::toSInteger64(double x) { - return x > (double)std::numeric_limits<int64_t>::min() && - x < (double)std::numeric_limits<int64_t>::max() + return (x > (double)std::numeric_limits<int64_t>::min() && + x < (double)std::numeric_limits<int64_t>::max()) ? (int64_t)x - : (x < 0 ? std::numeric_limits<int64_t>::min() - : std::numeric_limits<int64_t>::max()); + : (std::signbit(x) ? std::numeric_limits<int64_t>::min() + : std::numeric_limits<int64_t>::max()); } |