diff --git a/Lib/src/graphite2/src/inc/Main.h b/Lib/src/graphite2/src/inc/Main.h index 5c65469168..e938497c7b 100644 --- a/Lib/src/graphite2/src/inc/Main.h +++ b/Lib/src/graphite2/src/inc/Main.h @@ -77,15 +77,61 @@ class telemetry::category struct telemetry {}; #endif +// Checked multiplaction to catch overflow or underflow when allocating memory +#if defined(__has_builtin) + #if __has_builtin(__builtin_mul_overflow) + #define HAVE_BUILTIN_OVERFLOW + #endif +#elif defined(__GNUC__) && (__GNUC__ >= 5) && !defined(__INTEL_COMPILER) + #define HAVE_BUILTIN_OVERFLOW +#endif +#if defined(__has_include) + #if __has_include() && !defined(__CYGWIN__) + #define HAVE_INTSAFE_H + #endif +#elif defined(_WIN32) + #define HAVE_INTSAFE_H +#endif + +// Need to import intsafe into the top level namespace +#if defined(HAVE_INTSAFE_H) +} // namespace graphite2 + +#include + +namespace graphite2 { +#endif + +#if defined(HAVE_BUILTIN_OVERFLOW) +inline +bool checked_mul(const size_t a, const size_t b, size_t & t) { + return __builtin_mul_overflow(a, b, &t); +} +#elif defined(HAVE_INTSAFE_H) +inline +bool checked_mul(const size_t a, const size_t b, size_t & t) { + return SizeTMult(a, b, &t) == INTSAFE_E_ARITHMETIC_OVERFLOW; +} +#else +inline +bool checked_mul(const size_t a, const size_t b, size_t & t) { + t = a*b; + return (((a | b) & (~size_t(0) << (sizeof(size_t) << 2))) && (t / a != b)); +} +#endif + // typesafe wrapper around malloc for simple types // use free(pointer) to deallocate template T * gralloc(size_t n) { + size_t total; + if (checked_mul(n, sizeof(T), total)) + return 0; #ifdef GRAPHITE2_TELEMETRY - telemetry::count_bytes(sizeof(T) * n); + telemetry::count_bytes(total); #endif - return static_cast(malloc(sizeof(T) * n)); + return static_cast(malloc(total)); } template T * grzeroalloc(size_t n)