[aat] Skip terminator in VarSizedBinSearchArray<>

Fixes shaping with Apple Chancery on 10.13 again.  In that font,
there was a terminator segment, that was tripping off sanitize().
diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh
index 2c09a79..3ee96bc 100644
--- a/src/hb-aat-layout-common.hh
+++ b/src/hb-aat-layout-common.hh
@@ -76,6 +76,8 @@
 template <typename T>
 struct LookupSegmentSingle
 {
+  enum { TerminationWordCount = 2 };
+
   inline int cmp (hb_codepoint_t g) const {
     return g < first ? -1 : g <= last ? 0 : +1 ;
   }
@@ -134,6 +136,8 @@
 template <typename T>
 struct LookupSegmentArray
 {
+  enum { TerminationWordCount = 2 };
+
   inline const T* get_value (hb_codepoint_t glyph_id, const void *base) const
   {
     return first <= glyph_id && glyph_id <= last ? &(base+valuesZ)[glyph_id - first] : nullptr;
@@ -204,6 +208,8 @@
 template <typename T>
 struct LookupSingle
 {
+  enum { TerminationWordCount = 1 };
+
   inline int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh
index 8970ec7..9b412db 100644
--- a/src/hb-open-type.hh
+++ b/src/hb-open-type.hh
@@ -874,6 +874,22 @@
 
   HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (VarSizedBinSearchArrayOf, Type);
 
+  inline bool last_is_terminator (void) const
+  {
+    if (unlikely (!header.nUnits)) return false;
+
+    /* Gah.
+     *
+     * "The number of termination values that need to be included is table-specific.
+     * The value that indicates binary search termination is 0xFFFF." */
+    const HBUINT16 *words = &StructAtOffset<HBUINT16> (&bytesZ, (header.nUnits - 1) * header.unitSize);
+    unsigned int count = Type::TerminationWordCount;
+    for (unsigned int i = 0; i < count; i++)
+      if (words[i] != 0xFFFFu)
+        return false;
+    return true;
+  }
+
   inline const Type& operator [] (unsigned int i) const
   {
     if (unlikely (i >= get_length ())) return Null (Type);
@@ -884,7 +900,10 @@
     if (unlikely (i >= get_length ())) return Crap (Type);
     return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
   }
-  inline unsigned int get_length (void) const { return header.nUnits; }
+  inline unsigned int get_length (void) const
+  {
+    return header.nUnits - last_is_terminator ();
+  }
   inline unsigned int get_size (void) const
   { return header.static_size + header.nUnits * header.unitSize; }