ofz-8443: Integer-overflow in identifyCFF

https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=8443
diff --git a/fofi/FoFiIdentifier.cc b/fofi/FoFiIdentifier.cc
index 6e4ba70..3686322 100644
--- a/fofi/FoFiIdentifier.cc
+++ b/fofi/FoFiIdentifier.cc
@@ -16,6 +16,7 @@
 // Copyright (C) 2013 Christoph Duelli <duelli@melosgmbh.de>
 // Copyright (C) 2018 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2019 Christian Persch <chpe@src.gnome.org>
+// Copyright (C) 2019 LE GARREC Vincent <legarrec.vincent@gmail.com>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -26,6 +27,7 @@
 #include <string.h>
 #include <limits.h>
 #include "goo/gfile.h"
+#include "goo/GooCheckedOps.h"
 #include "FoFiIdentifier.h"
 
 //------------------------------------------------------------------------
@@ -614,9 +616,9 @@
       offset0 > offset1) {
     return fofiIdUnknown;
   }
-  pos = pos + 3 + (n + 1) * offSize1 + (int)offset0 - 1;
-  endPos = pos + 3 + (n + 1) * offSize1 + (int)offset1 - 1;
-  if (pos < 0 || endPos < 0 || pos > endPos) {
+  if (checkedAdd(pos + 3 + (n + 1) * offSize1, (int)offset0 - 1, &pos) ||
+    checkedAdd(pos + 3 + (n + 1) * offSize1, (int)offset1 - 1, &endPos) ||
+    pos < 0 || endPos < 0 || pos > endPos) {
     return fofiIdUnknown;
   }
   
diff --git a/goo/GooCheckedOps.h b/goo/GooCheckedOps.h
index 5eedf34..c49a621 100644
--- a/goo/GooCheckedOps.h
+++ b/goo/GooCheckedOps.h
@@ -12,17 +12,21 @@
 #ifndef GOO_CHECKED_OPS_H
 #define GOO_CHECKED_OPS_H
 
-#include <climits>
 #include <limits>
+#include <type_traits>
 
-inline bool checkedAssign(long long lz, int *z) {
-  static_assert(LLONG_MAX > INT_MAX, "Need type larger than int to perform overflow checks.");
+template<typename T> inline bool checkedAssign(long long lz, T *z) {
+  static_assert(std::numeric_limits<long long>::max() > std::numeric_limits<T>::max(),
+    "The max of long long type must be larger to perform overflow checks.");
+  static_assert(std::numeric_limits<long long>::min() < std::numeric_limits<T>::min(),
+    "The min of long long type must be smaller to perform overflow checks.");
 
-  if (lz > INT_MAX || lz < INT_MIN) {
+  if (lz > std::numeric_limits<T>::max() ||
+    lz < std::numeric_limits<T>::min()) {
     return true;
   }
 
-  *z = static_cast<int>(lz);
+  *z = static_cast<T>(lz);
   return false;
 }
 
@@ -30,18 +34,18 @@
   #define __has_builtin(x) 0
 #endif
 
-inline bool checkedAdd(int x, int y, int *z) {
-#if __GNUC__ >= 5 || __has_builtin(__builtin_sadd_overflow)
-  return __builtin_sadd_overflow(x, y, z);
+template<typename T> inline bool checkedAdd(T x, T y, T *z) {
+#if __GNUC__ >= 5 || __has_builtin(__builtin_add_overflow)
+  return __builtin_add_overflow(x, y, z);
 #else
   const auto lz = static_cast<long long>(x) + static_cast<long long>(y);
   return checkedAssign(lz, z);
 #endif
 }
 
-inline bool checkedMultiply(int x, int y, int *z) {
-#if __GNUC__ >= 5 || __has_builtin(__builtin_smul_overflow)
-  return __builtin_smul_overflow(x, y, z);
+template<typename T> inline bool checkedMultiply(T x, T y, T *z) {
+#if __GNUC__ >= 5 || __has_builtin(__builtin_mul_overflow)
+  return __builtin_mul_overflow(x, y, z);
 #else
   const auto lz = static_cast<long long>(x) * static_cast<long long>(y);
   return checkedAssign(lz, z);