Workaround VS/UCRT fmod bug

Recent versions of the Windows Universal CRT changed the behavior of
fmod for when the first parameter is negative. In particular, a result
of negative zero became positive zero. This is rarely critical but it
causes test failures and may effect some JS test suites or web pages.

The fix is to modify Modulo to check for a result of 0 when the first
parameter is negative and change the result to -0. That fixes four of
the five test failures and the fifth one is fixed by comparing the
results against Modulo instead of std::fmod.

Bug: chromium:915045
Change-Id: Ia4490ec98361a37006d6c338acd33f959fa3ccea
Reviewed-on: https://chromium-review.googlesource.com/c/1383091
Commit-Queue: Bruce Dawson <brucedawson@chromium.org>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58377}
diff --git a/src/utils.h b/src/utils.h
index a26aabc..c473b20 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -228,7 +228,11 @@
   // dividend is a zero and divisor is nonzero finite => result equals dividend
   if (!(std::isfinite(x) && (!std::isfinite(y) && !std::isnan(y))) &&
       !(x == 0 && (y != 0 && std::isfinite(y)))) {
-    x = fmod(x, y);
+    double result = fmod(x, y);
+    // Workaround MS bug in VS CRT in some OS versions, https://crbug.com/915045
+    // fmod(-17, +/-1) should equal -0.0 but now returns 0.0.
+    if (x < 0 && result == 0) result = -0.0;
+    x = result;
   }
   return x;
 #elif defined(V8_OS_AIX)
diff --git a/test/cctest/interpreter/test-interpreter.cc b/test/cctest/interpreter/test-interpreter.cc
index e835b92..ac459ea 100644
--- a/test/cctest/interpreter/test-interpreter.cc
+++ b/test/cctest/interpreter/test-interpreter.cc
@@ -241,7 +241,7 @@
     case Token::Value::DIV:
       return lhs / rhs;
     case Token::Value::MOD:
-      return std::fmod(lhs, rhs);
+      return Modulo(lhs, rhs);
     case Token::Value::BIT_OR:
       return (v8::internal::DoubleToInt32(lhs) |
               v8::internal::DoubleToInt32(rhs));