High firefox Logic Error 🔧 Commit mapped

Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impacthigh
DescriptionIncorrect boundary conditions in the Layout: Text and Fonts component
ComponentGraphics
Bug ClassLogic Error
Tracker2021863
Fix commit4b5b000117cf (firefox) +47/-9
CISA KEVNot listed
CreditedMatej Smycka
Disclosed2026-03-24

Files Changed

  • gfx/harfbuzz/src/hb-algs.hh
  • gfx/harfbuzz/src/hb-ot-shaper-arabic.cc
diff --git a/gfx/harfbuzz/src/hb-algs.hh b/gfx/harfbuzz/src/hb-algs.hh
index c58049621af..b28a587d475 100644
--- a/gfx/harfbuzz/src/hb-algs.hh
+++ b/gfx/harfbuzz/src/hb-algs.hh
@@ -1200,6 +1200,21 @@ hb_unsigned_mul_overflows (unsigned int count, unsigned int size, unsigned *resu
   return (size > 0) && (count >= ((unsigned int) -1) / size);
 }
 
+static inline bool
+hb_unsigned_add_overflows (unsigned int a, unsigned int b, unsigned *result = nullptr)
+{
+#if hb_has_builtin(__builtin_add_overflow)
+  unsigned stack_result;
+  if (!result)
+    result = &stack_result;
+  return __builtin_add_overflow (a, b, result);
+#endif
+
+  if (result)
+    *result = a + b;
+  return b > (unsigned int) -1 - a;
+}
+
 
 /*
  * Sort and search.
diff --git a/gfx/harfbuzz/src/hb-ot-shaper-arabic.cc b/gfx/harfbuzz/src/hb-ot-shaper-arabic.cc
index 69320eb9544..2a05af1462e 100644
--- a/gfx/harfbuzz/src/hb-ot-shaper-arabic.cc
+++ b/gfx/harfbuzz/src/hb-ot-shaper-arabic.cc
@@ -561,20 +561,29 @@ apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED,
       DEBUG_MSG (ARABIC, nullptr, "fixed tiles:     count=%d width=%" PRId32, n_fixed, w_fixed);
       DEBUG_MSG (ARABIC, nullptr, "repeating tiles: count=%d width=%" PRId32, n_repeating, w_repeating);
 
+      static constexpr unsigned STCH_MAX_GLYPHS = 256;
+
       /* Number of additional times to repeat each repeating tile. */
-      int n_copies = 0;
+      unsigned int n_copies = 0;
 
-      hb_position_t w_remaining = w_total - w_fixed;
-      if (sign * w_remaining > sign * w_repeating && sign * w_repeating > 0)
-	n_copies = (sign * w_remaining) / (sign * w_repeating) - 1;
+      int64_t w_remaining_signed = (int64_t) w_total - w_fixed;
+      int64_t w_repeating_signed = w_repeating;
+      if (sign < 0)
+      {
+	w_remaining_signed = -w_remaining_signed;
+	w_repeating_signed = -w_repeating_signed;
+      }
+      hb_position_t w_remaining = (hb_position_t) (w_total - w_fixed);
+      if (w_remaining_signed > w_repeating_signed && w_repeating_signed > 0)
+	n_copies = w_remaining_signed / w_repeating_signed - 1;
 
       /* See if we can improve the fit by adding an extra repeat and squeezing them together a bit. */
       hb_position_t extra_repeat_overlap = 0;
-      hb_position_t shortfall = sign * w_remaining - sign * w_repeating * (n_copies + 1);
+      int64_t shortfall = w_remaining_signed - w_repeating_signed * (n_copies + 1);
       if (shortfall > 0 && n_repeating > 0)
       {
 	++n_copies;
-	hb_position_t excess = (n_copies + 1) * sign * w_repeating - sign * w_remaining;
+	int64_t excess = (n_copies + 1) * w_repeating_signed - w_remaining_signed;
 	if (excess > 0)
 	{
 	  extra_repeat_overlap = excess / (n_copies * n_repeating);
@@ -582,10 +591,22 @@ apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED,
 	}
       }
 
+      unsigned int max_copies = 0;
+      if (n_repeating > 0)
+      {
+	unsigned int base_glyphs = n_fixed + n_repeating;
+	if (base_glyphs < STCH_MAX_GLYPHS)
+	  max_copies = (STCH_MAX_GLYPHS - base_glyphs) / n_repeating;
+      }
+      n_copies = hb_min (n_copies, max_copies);
+
       if (step == MEASURE)
       {
-	extra_glyphs_needed += n_copies * n_repeating;
-	DEBUG_MSG (ARABIC, nullptr, "will add extra %d copies of repeating tiles", n_copies);
+	unsigned int added_glyphs = 0;
+	if (unlikely (hb_unsigned_mul_overflows (n_copies, n_repeating, &added_glyphs) ||
+		      hb_unsigned_add_overflows (extra_glyphs_needed, added_glyphs, &extra_glyphs_needed)))
+	  break;
+	DEBUG_MSG (ARABIC, nullptr, "will add extra %u copies of repeating tiles", n_copies);
       }
       else
       {
@@ -629,7 +650,9 @@ apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED,
 
     if (step == MEASURE)
     {
-      if (unlikely (!buffer->ensure (count + extra_glyphs_needed)))
+      unsigned int total_glyphs = 0;
+      if (unlikely (hb_unsigned_add_overflows (count, extra_glyphs_needed, &total_glyphs) ||
+		    !buffer->ensure (total_glyphs)))
 	break;
     }
     else
Loading diff…