Merge pull request #4168 from googlefonts/subset_name_collect

[subset] name_id closure 
diff --git a/src/OT/Color/COLR/COLR.hh b/src/OT/Color/COLR/COLR.hh
index 31be658..3c774e8 100644
--- a/src/OT/Color/COLR/COLR.hh
+++ b/src/OT/Color/COLR/COLR.hh
@@ -746,8 +746,8 @@
     c->funcs->sweep_gradient (c->data, &cl,
 			      centerX + c->instancer (varIdxBase, 0),
 			      centerY + c->instancer (varIdxBase, 1),
-                              (startAngle.to_float (c->instancer (varIdxBase, 2)) + 1) * (float) M_PI,
-                              (endAngle.to_float   (c->instancer (varIdxBase, 3)) + 1) * (float) M_PI);
+                              (startAngle.to_float (c->instancer (varIdxBase, 2)) + 1) * HB_PI,
+                              (endAngle.to_float   (c->instancer (varIdxBase, 3)) + 1) * HB_PI);
   }
 
   HBUINT8			format; /* format = 8(noVar) or 9 (Var) */
diff --git a/src/OT/glyf/CompositeGlyph.hh b/src/OT/glyf/CompositeGlyph.hh
index edf8cd8..ad9ce82 100644
--- a/src/OT/glyf/CompositeGlyph.hh
+++ b/src/OT/glyf/CompositeGlyph.hh
@@ -330,7 +330,10 @@
     for (const auto &component : it)
     {
       /* last 4 points in deltas are phantom points and should not be included */
-      if (i >= deltas.length - 4) return false;
+      if (i >= deltas.length - 4) {
+        free (o);
+        return false;
+      }
 
       unsigned comp_len = component.get_size ();
       if (component.is_anchored ())
diff --git a/src/OT/glyf/SubsetGlyph.hh b/src/OT/glyf/SubsetGlyph.hh
index 795925b..a38a57a 100644
--- a/src/OT/glyf/SubsetGlyph.hh
+++ b/src/OT/glyf/SubsetGlyph.hh
@@ -18,6 +18,7 @@
   Glyph source_glyph;
   hb_bytes_t dest_start;  /* region of source_glyph to copy first */
   hb_bytes_t dest_end;    /* region of source_glyph to copy second */
+  bool allocated;
 
   bool serialize (hb_serialize_context_t *c,
 		  bool use_short_loca,
@@ -60,12 +61,18 @@
   bool compile_bytes_with_deltas (const hb_subset_plan_t *plan,
                                   hb_font_t *font,
                                   const glyf_accelerator_t &glyf)
-  { return source_glyph.compile_bytes_with_deltas (plan, font, glyf, dest_start, dest_end); }
+  {
+    allocated = source_glyph.compile_bytes_with_deltas (plan, font, glyf, dest_start, dest_end);
+    return allocated;
+  }
 
   void free_compiled_bytes ()
   {
-    dest_start.fini ();
-    dest_end.fini ();
+    if (likely (allocated)) {
+      allocated = false;
+      dest_start.fini ();
+      dest_end.fini ();
+    }
   }
 
   void drop_hints_bytes ()
diff --git a/src/OT/glyf/VarCompositeGlyph.hh b/src/OT/glyf/VarCompositeGlyph.hh
index f1d48be..f543eff 100644
--- a/src/OT/glyf/VarCompositeGlyph.hh
+++ b/src/OT/glyf/VarCompositeGlyph.hh
@@ -145,7 +145,7 @@
 		      float rotation)
   {
     // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240
-    rotation = rotation * float (M_PI);
+    rotation = rotation * HB_PI;
     float c = cosf (rotation);
     float s = sinf (rotation);
     float other[6] = {c, s, -s, c, 0.f, 0.f};
@@ -156,8 +156,8 @@
 		    float skewX, float skewY)
   {
     // https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255
-    skewX = skewX * float (M_PI);
-    skewY = skewY * float (M_PI);
+    skewX = skewX * HB_PI;
+    skewY = skewY * HB_PI;
     float other[6] = {1.f, tanf (skewY), tanf (skewX), 1.f, 0.f, 0.f};
     transform (matrix, trans, other);
   }
diff --git a/src/OT/glyf/glyf.hh b/src/OT/glyf/glyf.hh
index bc5608d..7d2522e 100644
--- a/src/OT/glyf/glyf.hh
+++ b/src/OT/glyf/glyf.hh
@@ -131,7 +131,7 @@
 
     bool result = glyf_prime->serialize (c->serializer, glyphs.writer (), use_short_loca, c->plan);
     if (c->plan->normalized_coords && !c->plan->pinned_at_default)
-      _free_compiled_subset_glyphs (glyphs, glyphs.length - 1);
+      _free_compiled_subset_glyphs (glyphs);
 
     if (!result) return false;
 
@@ -150,9 +150,9 @@
   hb_font_t *
   _create_font_for_instancing (const hb_subset_plan_t *plan) const;
 
-  void _free_compiled_subset_glyphs (hb_vector_t<glyf_impl::SubsetGlyph> &glyphs, unsigned index) const
+  void _free_compiled_subset_glyphs (hb_vector_t<glyf_impl::SubsetGlyph> &glyphs) const
   {
-    for (unsigned i = 0; i <= index && i < glyphs.length; i++)
+    for (unsigned i = 0; i < glyphs.length; i++)
       glyphs[i].free_compiled_bytes ();
   }
 
@@ -424,7 +424,6 @@
   unsigned num_glyphs = plan->num_output_glyphs ();
   if (!glyphs.resize (num_glyphs)) return false;
 
-  unsigned idx = 0;
   for (auto p : plan->glyph_map->iter ())
   {
     unsigned new_gid = p.second;
@@ -452,11 +451,10 @@
       if (unlikely (!subset_glyph.compile_bytes_with_deltas (plan, font, glyf)))
       {
         // when pinned at default, only bounds are updated, thus no need to free
-        if (!plan->pinned_at_default && idx > 0)
-          _free_compiled_subset_glyphs (glyphs, idx - 1);
+        if (!plan->pinned_at_default)
+          _free_compiled_subset_glyphs (glyphs);
         return false;
       }
-      idx++;
     }
   }
   return true;
diff --git a/src/hb-cairo-utils.cc b/src/hb-cairo-utils.cc
index d841994..0f94d81 100644
--- a/src/hb-cairo-utils.cc
+++ b/src/hb-cairo-utils.cc
@@ -41,8 +41,6 @@
 
 #define PREALLOCATED_COLOR_STOPS 16
 
-#define _2_M_PIf (2.f * float (M_PI))
-
 typedef struct {
   float r, g, b, a;
 } hb_cairo_color_t;
@@ -525,7 +523,7 @@
   cairo_mesh_pattern_end_patch (pattern);
 }
 
-#define MAX_ANGLE ((float) M_PI / 8.f)
+#define MAX_ANGLE (HB_PI / 8.f)
 
 static void
 _hb_cairo_add_sweep_gradient_patches1 (float cx, float cy, float radius,
@@ -608,7 +606,7 @@
 					       start_angle, &c,
 					       pattern);
       }
-      if (end_angle < _2_M_PIf)
+      if (end_angle < HB_2_PI)
       {
 	c.r = hb_color_get_red (stops[n_stops - 1].color) / 255.;
 	c.g = hb_color_get_green (stops[n_stops - 1].color) / 255.;
@@ -616,7 +614,7 @@
 	c.a = hb_color_get_alpha (stops[n_stops - 1].color) / 255.;
 	_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
 					       end_angle, &c,
-					       _2_M_PIf,  &c,
+					       HB_2_PI,  &c,
 					       pattern);
       }
     }
@@ -680,7 +678,7 @@
       color0 = colors[n_stops-1];
       _hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
 					     0.,       &color0,
-					     _2_M_PIf, &color0,
+					     HB_2_PI, &color0,
 					     pattern);
       goto done;
     }
@@ -692,7 +690,7 @@
 
     for (pos++; pos < n_stops; pos++)
     {
-      if (angles[pos] <= _2_M_PIf)
+      if (angles[pos] <= HB_2_PI)
       {
 	_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
 					       angles[pos - 1], &colors[pos-1],
@@ -701,11 +699,11 @@
       }
       else
       {
-	float k = (_2_M_PIf - angles[pos - 1]) / (angles[pos] - angles[pos - 1]);
+	float k = (HB_2_PI - angles[pos - 1]) / (angles[pos] - angles[pos - 1]);
 	_hb_cairo_interpolate_colors (&colors[pos - 1], &colors[pos], k, &color1);
 	_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
 					       angles[pos - 1], &colors[pos - 1],
-					       _2_M_PIf,        &color1,
+					       HB_2_PI,        &color1,
 					       pattern);
 	break;
       }
@@ -717,7 +715,7 @@
       color0 = colors[n_stops - 1];
       _hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
 					     angles[n_stops - 1], &color0,
-					     _2_M_PIf,            &color0,
+					     HB_2_PI,            &color0,
 					     pattern);
       goto done;
     }
@@ -801,14 +799,14 @@
 						 a1, c1,
 						 pattern);
 	}
-	else if (a1 >= _2_M_PIf)
+	else if (a1 >= HB_2_PI)
 	{
 	  hb_cairo_color_t color;
-	  float f = (_2_M_PIf - a0)/(a1 - a0);
+	  float f = (HB_2_PI - a0)/(a1 - a0);
 	  _hb_cairo_interpolate_colors (c0, c1, f, &color);
 	  _hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
 						 a0,       c0,
-						 _2_M_PIf, &color,
+						 HB_2_PI, &color,
 						 pattern);
 	  goto done;
 	}
diff --git a/src/hb-ft-colr.hh b/src/hb-ft-colr.hh
index b345793..fa5712f 100644
--- a/src/hb-ft-colr.hh
+++ b/src/hb-ft-colr.hh
@@ -301,8 +301,8 @@
       c->funcs->sweep_gradient (c->data, &cl,
 				paint.u.sweep_gradient.center.x / 65536.f,
 				paint.u.sweep_gradient.center.y / 65536.f,
-				(paint.u.sweep_gradient.start_angle / 65536.f + 1) * (float) M_PI,
-				(paint.u.sweep_gradient.end_angle / 65536.f + 1) * (float) M_PI);
+				(paint.u.sweep_gradient.start_angle / 65536.f + 1) * HB_PI,
+				(paint.u.sweep_gradient.end_angle / 65536.f + 1) * HB_PI);
     }
     break;
     case FT_COLR_PAINTFORMAT_GLYPH:
diff --git a/src/hb-outline.cc b/src/hb-outline.cc
index 0657e0e..29b1f53 100644
--- a/src/hb-outline.cc
+++ b/src/hb-outline.cc
@@ -4,7 +4,6 @@
  * Copyright © 2005  Werner Lemberg
  * Copyright © 2013-2015  Alexei Podtelezhnikov
  *
- *
  *  This is part of HarfBuzz, a text shaping library.
  *
  * Permission is hereby granted, without written agreement and without
diff --git a/src/hb-paint.hh b/src/hb-paint.hh
index f7b71aa..d291a4b 100644
--- a/src/hb-paint.hh
+++ b/src/hb-paint.hh
@@ -203,8 +203,8 @@
     if (!a)
       return false;
 
-    float cc = cosf (a * (float) M_PI);
-    float ss = sinf (a * (float) M_PI);
+    float cc = cosf (a * HB_PI);
+    float ss = sinf (a * HB_PI);
     push_transform (paint_data, cc, ss, -ss, cc, 0.f, 0.f);
     return true;
   }
@@ -216,8 +216,8 @@
     if (!sx && !sy)
       return false;
 
-    float x = tanf (-sx * (float) M_PI);
-    float y = tanf (+sy * (float) M_PI);
+    float x = tanf (-sx * HB_PI);
+    float y = tanf (+sy * HB_PI);
     push_transform (paint_data, 1.f, y, x, 1.f, 0.f, 0.f);
     return true;
   }
diff --git a/src/hb-style.cc b/src/hb-style.cc
index c7d7d71..bd5cb5c 100644
--- a/src/hb-style.cc
+++ b/src/hb-style.cc
@@ -46,13 +46,13 @@
 static inline float
 _hb_angle_to_ratio (float a)
 {
-  return tanf (a * float (-M_PI / 180.));
+  return tanf (a * -HB_PI / 180.f);
 }
 
 static inline float
 _hb_ratio_to_angle (float r)
 {
-  return atanf (r) * float (-180. / M_PI);
+  return atanf (r) * -180.f / HB_PI;
 }
 
 /**
diff --git a/src/hb.hh b/src/hb.hh
index d09849e..30b3de4 100644
--- a/src/hb.hh
+++ b/src/hb.hh
@@ -509,6 +509,12 @@
 static_assert ((sizeof (hb_var_int_t) == 4), "");
 
 
+/* Pie time. */
+// https://github.com/harfbuzz/harfbuzz/issues/4166
+#define HB_PI 3.14159265358979f
+#define HB_2_PI (2.f * HB_PI)
+
+
 /* Headers we include for everyone.  Keep topologically sorted by dependency.
  * They express dependency amongst themselves, but no other file should include
  * them directly.*/
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-4801020053291008 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-4801020053291008
new file mode 100644
index 0000000..5758a65
--- /dev/null
+++ b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-4801020053291008
Binary files differ
diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5388270411579392 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5388270411579392
new file mode 100644
index 0000000..d39badd
--- /dev/null
+++ b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5388270411579392
Binary files differ
diff --git a/test/fuzzing/hb-subset-fuzzer.cc b/test/fuzzing/hb-subset-fuzzer.cc
index caeafb1..93153ed 100644
--- a/test/fuzzing/hb-subset-fuzzer.cc
+++ b/test/fuzzing/hb-subset-fuzzer.cc
@@ -64,12 +64,24 @@
       };
 
   hb_subset_input_t *input = hb_subset_input_create_or_fail ();
+  if (!input)
+  {
+    hb_face_destroy (face);
+    hb_blob_destroy (blob);
+    return 0;
+  }
   trySubset (face, text, sizeof (text) / sizeof (hb_codepoint_t), flags, input);
 
   unsigned num_axes;
   hb_codepoint_t text_from_data[16];
   if (size > sizeof (text_from_data) + sizeof (flags) + sizeof(num_axes)) {
     hb_subset_input_t *input = hb_subset_input_create_or_fail ();
+    if (!input)
+    {
+      hb_face_destroy (face);
+      hb_blob_destroy (blob);
+      return 0;
+    }
     size -= sizeof (text_from_data);
     memcpy (text_from_data,
 	    data + size,