Use class templates for Null objects

This allows partial-instantiating custom Null object for template Lookup<T>.
Before, this had to be handcoded per instantiation.  Apparently I missed
adding one for AAT::ankr.lookupTable, so it was getting the wrong (generic)
null for Lookup object, which is wrong and unsafe.

Fixes https://bugs.chromium.org/p/chromium/issues/detail?id=944346
diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh
index 27ade28..2508276 100644
--- a/src/hb-aat-layout-common.hh
+++ b/src/hb-aat-layout-common.hh
@@ -418,15 +418,11 @@
 } /* Close namespace. */
 /* Ugly hand-coded null objects for template Lookup<> :(. */
 extern HB_INTERNAL const unsigned char _hb_Null_AAT_Lookup[2];
-template <>
-/*static*/ inline const AAT::Lookup<OT::HBUINT16>& Null<AAT::Lookup<OT::HBUINT16> > ()
-{ return *reinterpret_cast<const AAT::Lookup<OT::HBUINT16> *> (_hb_Null_AAT_Lookup); }
-template <>
-/*static*/ inline const AAT::Lookup<OT::HBUINT32>& Null<AAT::Lookup<OT::HBUINT32> > ()
-{ return *reinterpret_cast<const AAT::Lookup<OT::HBUINT32> *> (_hb_Null_AAT_Lookup); }
-template <>
-/*static*/ inline const AAT::Lookup<OT::Offset<OT::HBUINT16, false> >& Null<AAT::Lookup<OT::Offset<OT::HBUINT16, false> > > ()
-{ return *reinterpret_cast<const AAT::Lookup<OT::Offset<OT::HBUINT16, false> > *> (_hb_Null_AAT_Lookup); }
+template <typename T>
+struct Null<AAT::Lookup<T> > {
+  static AAT::Lookup<T> const & get_null ()
+  { return *reinterpret_cast<const AAT::Lookup<T> *> (_hb_Null_AAT_Lookup); }
+};
 namespace AAT {
 
 enum { DELETED_GLYPH = 0xFFFF };
diff --git a/src/hb-null.hh b/src/hb-null.hh
index 204c2fe..baddd99 100644
--- a/src/hb-null.hh
+++ b/src/hb-null.hh
@@ -105,15 +105,18 @@
 
 /* Generic nul-content Null objects. */
 template <typename Type>
-static inline Type const & Null () {
-  static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
-  return *reinterpret_cast<Type const *> (_hb_NullPool);
-}
+struct Null {
+  static Type const & get_null ()
+  {
+    static_assert (hb_null_size (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
+    return *reinterpret_cast<Type const *> (_hb_NullPool);
+  }
+};
 template <typename QType>
 struct NullHelper
 {
   typedef typename hb_remove_const (typename hb_remove_reference (QType)) Type;
-  static const Type & get_null () { return Null<Type> (); }
+  static const Type & get_null () { return Null<Type>::get_null (); }
 };
 #define Null(Type) NullHelper<Type>::get_null ()
 
@@ -122,9 +125,11 @@
 	} /* Close namespace. */ \
 	extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]; \
 	template <> \
-	/*static*/ inline const Namespace::Type& Null<Namespace::Type> () { \
-	  return *reinterpret_cast<const Namespace::Type *> (_hb_Null_##Namespace##_##Type); \
-	} \
+	struct Null<Namespace::Type> { \
+	  static Namespace::Type const & get_null () { \
+	    return *reinterpret_cast<const Namespace::Type *> (_hb_Null_##Namespace##_##Type); \
+	  } \
+	}; \
 	namespace Namespace { \
 	static_assert (true, "Just so we take semicolon after.")
 #define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \
@@ -134,10 +139,12 @@
 #define DECLARE_NULL_INSTANCE(Type) \
 	extern HB_INTERNAL const Type _hb_Null_##Type; \
 	template <> \
-	/*static*/ inline const Type& Null<Type> () { \
-	  return _hb_Null_##Type; \
-	} \
-static_assert (true, "Just so we take semicolon after.")
+	struct Null<Type> { \
+	  static Type const & get_null () { \
+	    return _hb_Null_##Type; \
+	  } \
+	}; \
+	static_assert (true, "Just so we take semicolon after.")
 #define DEFINE_NULL_INSTANCE(Type) \
 	const Type _hb_Null_##Type
 
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5748102301614080 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5748102301614080
new file mode 100644
index 0000000..4cb979d
--- /dev/null
+++ b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-harfbuzz_fuzzer-5748102301614080
Binary files differ