[algs] Add output argument to hb_unsigned_mul_overflows()
diff --git a/src/hb-algs.hh b/src/hb-algs.hh
index 9659d63..64e9142 100644
--- a/src/hb-algs.hh
+++ b/src/hb-algs.hh
@@ -854,13 +854,17 @@
  */
 
 static inline bool
-hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
+hb_unsigned_mul_overflows (unsigned int count, unsigned int size, unsigned *result = nullptr)
 {
 #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
-  unsigned result;
-  return __builtin_mul_overflow (count, size, &result);
+  unsigned stack_result;
+  if (!result)
+    result = &stack_result;
+  return __builtin_mul_overflow (count, size, result);
 #endif
 
+  if (result)
+    *result = count * size;
   return (size > 0) && (count >= ((unsigned int) -1) / size);
 }
 
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 2fe2eea..44b5dcb 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -172,12 +172,13 @@
   while (size >= new_allocated)
     new_allocated += (new_allocated >> 1) + 32;
 
-  static_assert ((sizeof (info[0]) == sizeof (pos[0])), "");
-  if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0]))))
+  unsigned new_bytes;
+  if (unlikely (hb_unsigned_mul_overflows (new_allocated, sizeof (info[0]), &new_bytes)))
     goto done;
 
-  new_pos = (hb_glyph_position_t *) hb_realloc (pos, new_allocated * sizeof (pos[0]));
-  new_info = (hb_glyph_info_t *) hb_realloc (info, new_allocated * sizeof (info[0]));
+  static_assert (sizeof (info[0]) == sizeof (pos[0]), "");
+  new_pos = (hb_glyph_position_t *) hb_realloc (pos, new_bytes);
+  new_info = (hb_glyph_info_t *) hb_realloc (info, new_bytes);
 
 done:
   if (unlikely (!new_pos || !new_info))
@@ -313,15 +314,14 @@
   serial = 0;
   shaping_failed = false;
   scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
-  if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_LEN_FACTOR)))
+  unsigned mul;
+  if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_LEN_FACTOR, &mul)))
   {
-    max_len = hb_max (len * HB_BUFFER_MAX_LEN_FACTOR,
-		      (unsigned) HB_BUFFER_MAX_LEN_MIN);
+    max_len = hb_max (mul, (unsigned) HB_BUFFER_MAX_LEN_MIN);
   }
-  if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_OPS_FACTOR)))
+  if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_OPS_FACTOR, &mul)))
   {
-    max_ops = hb_max (len * HB_BUFFER_MAX_OPS_FACTOR,
-		      (unsigned) HB_BUFFER_MAX_OPS_MIN);
+    max_ops = hb_max (mul, (unsigned) HB_BUFFER_MAX_OPS_MIN);
   }
 }
 void
diff --git a/src/hb-sanitize.hh b/src/hb-sanitize.hh
index 65c2772..bd3250e 100644
--- a/src/hb-sanitize.hh
+++ b/src/hb-sanitize.hh
@@ -198,10 +198,11 @@
   void start_processing ()
   {
     reset_object ();
-    if (unlikely (hb_unsigned_mul_overflows (this->end - this->start, HB_SANITIZE_MAX_OPS_FACTOR)))
+    unsigned m;
+    if (unlikely (hb_unsigned_mul_overflows (this->end - this->start, HB_SANITIZE_MAX_OPS_FACTOR, &m)))
       this->max_ops = HB_SANITIZE_MAX_OPS_MAX;
     else
-      this->max_ops = hb_clamp ((unsigned) (this->end - this->start) * HB_SANITIZE_MAX_OPS_FACTOR,
+      this->max_ops = hb_clamp (m,
 				(unsigned) HB_SANITIZE_MAX_OPS_MIN,
 				(unsigned) HB_SANITIZE_MAX_OPS_MAX);
     this->edit_count = 0;
@@ -252,8 +253,9 @@
 		    unsigned int a,
 		    unsigned int b) const
   {
-    return !hb_unsigned_mul_overflows (a, b) &&
-	   this->check_range (base, a * b);
+    unsigned m;
+    return !hb_unsigned_mul_overflows (a, b, &m) &&
+	   this->check_range (base, m);
   }
 
   template <typename T>
@@ -262,8 +264,9 @@
 		    unsigned int b,
 		    unsigned int c) const
   {
-    return !hb_unsigned_mul_overflows (a, b) &&
-	   this->check_range (base, a * b, c);
+    unsigned m;
+    return !hb_unsigned_mul_overflows (a, b, &m) &&
+	   this->check_range (base, m, c);
   }
 
   template <typename T>