Guard against buggy ucrt\math.h.

BUG=666707

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=5089

CQ_INCLUDE_TRYBOTS=master.client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot

Change-Id: I3bebfdf635d541d92fb84236f0f6fae2da39d691
Reviewed-on: https://skia-review.googlesource.com/5089
Reviewed-by: Bruce Dawson <brucedawson@google.com>
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
diff --git a/include/private/SkFixed.h b/include/private/SkFixed.h
index cdde093..07ac9d2 100644
--- a/include/private/SkFixed.h
+++ b/include/private/SkFixed.h
@@ -9,7 +9,7 @@
 #define SkFixed_DEFINED
 
 #include "SkScalar.h"
-#include "math.h"
+#include "SkSafe_math.h"
 
 #include "SkTypes.h"
 
diff --git a/include/private/SkFloatBits.h b/include/private/SkFloatBits.h
index 7aa13cf..4909926 100644
--- a/include/private/SkFloatBits.h
+++ b/include/private/SkFloatBits.h
@@ -10,7 +10,7 @@
 #define SkFloatBits_DEFINED
 
 #include "SkTypes.h"
-#include <math.h>
+#include "SkSafe_math.h"
 
 /** Convert a sign-bit int (i.e. float interpreted as int) into a 2s compliement
     int. This also converts -0 (0x80000000) to 0. Doing this to a float allows
diff --git a/include/private/SkFloatingPoint.h b/include/private/SkFloatingPoint.h
index 6a6edf3..f3acf48 100644
--- a/include/private/SkFloatingPoint.h
+++ b/include/private/SkFloatingPoint.h
@@ -11,8 +11,7 @@
 #define SkFloatingPoint_DEFINED
 
 #include "SkTypes.h"
-
-#include <math.h>
+#include "SkSafe_math.h"
 #include <float.h>
 
 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1
diff --git a/include/private/SkSafe_math.h b/include/private/SkSafe_math.h
new file mode 100644
index 0000000..144b28a
--- /dev/null
+++ b/include/private/SkSafe_math.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkSafe_math_DEFINED
+#define SkSafe_math_DEFINED
+
+// This file protects against known bugs in ucrt\math.h.
+// Namely, that header defines inline methods without marking them static,
+// which makes it very easy to cause ODR violations and ensuing chaos.
+//
+// TODO: other headers?  Here are some potential problem headers:
+// $ grep -R __inline * | grep -v static | cut -f 1 -d: | sort | uniq
+//   corecrt.h
+//   corecrt_stdio_config.h
+//   ctype.h
+//   fenv.h
+//   locale.h
+//   malloc.h
+//   math.h
+//   tchar.h
+//   wchar.h
+// I took a quick look through other headers outside math.h.
+// Nothing looks anywhere near as likely to be used by Skia as math.h.
+
+#if defined(_MSC_VER) && !defined(_INC_MATH)
+    // Our strategy here is to simply inject "static" into the headers
+    // where it should have been written, just before __inline.
+    //
+    // Most inline-but-not-static methods in math.h are 32-bit only,
+    // but not all of them (see frexpf, hypothf, ldexpf...).  So to
+    // be safe, 32- and 64-bit builds both get this treatment.
+
+    #define __inline static __inline
+    #include <math.h>
+    #undef __inline
+
+    #if !defined(_INC_MATH)
+        #error Hmm.  Looks like math.h has changed its header guards.
+    #endif
+
+    #define INC_MATH_IS_SAFE_NOW
+
+#else
+    #include <math.h>
+
+#endif
+
+#endif//SkSafe_math_DEFINED
diff --git a/src/core/SkNx.h b/src/core/SkNx.h
index ad0fc0d..8431afb 100644
--- a/src/core/SkNx.h
+++ b/src/core/SkNx.h
@@ -8,10 +8,10 @@
 #ifndef SkNx_DEFINED
 #define SkNx_DEFINED
 
+#include "SkSafe_math.h"
 #include "SkScalar.h"
 #include "SkTypes.h"
 #include <limits>
-#include <math.h>
 #include <type_traits>
 
 // These _abi types are data-only, and so can be used to store SkNx in structs or
diff --git a/src/opts/SkOpts_avx.cpp b/src/opts/SkOpts_avx.cpp
index b5df2b6..06e46d9 100644
--- a/src/opts/SkOpts_avx.cpp
+++ b/src/opts/SkOpts_avx.cpp
@@ -5,10 +5,15 @@
  * found in the LICENSE file.
  */
 
+#include "SkSafe_math.h"   // Keep this first.
 #include "SkOpts.h"
 
 #define SK_OPTS_NS avx
 
+#if defined(_INC_MATH) && !defined(INC_MATH_IS_SAFE_NOW)
+    #error We have included ucrt\math.h without protecting it against ODR violation.
+#endif
+
 namespace SkOpts {
     void Init_avx() { }
 }
diff --git a/src/opts/SkOpts_hsw.cpp b/src/opts/SkOpts_hsw.cpp
index 8c31af5..96465b8 100644
--- a/src/opts/SkOpts_hsw.cpp
+++ b/src/opts/SkOpts_hsw.cpp
@@ -5,11 +5,16 @@
  * found in the LICENSE file.
  */
 
+#include "SkSafe_math.h"   // Keep this first.
 #include "SkOpts.h"
 
 #define SK_OPTS_NS hsw
 #include "SkRasterPipeline_opts.h"
 
+#if defined(_INC_MATH) && !defined(INC_MATH_IS_SAFE_NOW)
+    #error We have included ucrt\math.h without protecting it against ODR violation.
+#endif
+
 namespace SkOpts {
     void Init_hsw() {
         compile_pipeline = hsw::compile_pipeline;
diff --git a/src/pathops/SkPathOpsTypes.h b/src/pathops/SkPathOpsTypes.h
index 87291f7..f525ea4 100644
--- a/src/pathops/SkPathOpsTypes.h
+++ b/src/pathops/SkPathOpsTypes.h
@@ -8,12 +8,12 @@
 #define SkPathOpsTypes_DEFINED
 
 #include <float.h>  // for FLT_EPSILON
-#include <math.h>   // for fabs, sqrt
 
 #include "SkFloatingPoint.h"
 #include "SkPath.h"
 #include "SkPathOps.h"
 #include "SkPathOpsDebug.h"
+#include "SkSafe_math.h"  // for fabs, sqrt
 #include "SkScalar.h"
 
 enum SkPathOpsMask {
@@ -146,7 +146,7 @@
     SkOpPhase phase() const {
         return fPhase;
     }
-    
+
     void resetAllocatedOpSpan() {
         fAllocatedOpSpan = false;
     }
@@ -158,7 +158,7 @@
     void setCoincidence(SkOpCoincidence* coincidence) {
         fCoincidence = coincidence;
     }
-    
+
     void setContourHead(SkOpContourHead* contourHead) {
         fContourHead = contourHead;
     }