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;
}