ed1787d
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
ed1787d
From: Zhang Boyang <zhangboyang.id@gmail.com>
ed1787d
Date: Mon, 24 Oct 2022 08:05:35 +0800
ed1787d
Subject: [PATCH] font: Fix an integer underflow in blit_comb()
ed1787d
ed1787d
The expression (ctx.bounds.height - combining_glyphs[i]->height) / 2 may
ed1787d
evaluate to a very big invalid value even if both ctx.bounds.height and
ed1787d
combining_glyphs[i]->height are small integers. For example, if
ed1787d
ctx.bounds.height is 10 and combining_glyphs[i]->height is 12, this
ed1787d
expression evaluates to 2147483647 (expected -1). This is because
ed1787d
coordinates are allowed to be negative but ctx.bounds.height is an
ed1787d
unsigned int. So, the subtraction operates on unsigned ints and
ed1787d
underflows to a very big value. The division makes things even worse.
ed1787d
The quotient is still an invalid value even if converted back to int.
ed1787d
ed1787d
This patch fixes the problem by casting ctx.bounds.height to int. As
ed1787d
a result the subtraction will operate on int and grub_uint16_t which
ed1787d
will be promoted to an int. So, the underflow will no longer happen. Other
ed1787d
uses of ctx.bounds.height (and ctx.bounds.width) are also casted to int,
ed1787d
to ensure coordinates are always calculated on signed integers.
ed1787d
ed1787d
Fixes: CVE-2022-3775
ed1787d
ed1787d
Reported-by: Daniel Axtens <dja@axtens.net>
ed1787d
Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com>
ed1787d
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
ed1787d
(cherry picked from commit 6d2668dea3774ed74c4cd1eadd146f1b846bc3d4)
ed1787d
---
ed1787d
 grub-core/font/font.c | 16 ++++++++--------
ed1787d
 1 file changed, 8 insertions(+), 8 deletions(-)
ed1787d
ed1787d
diff --git a/grub-core/font/font.c b/grub-core/font/font.c
ed1787d
index 193dfec045..12a5f0d08c 100644
ed1787d
--- a/grub-core/font/font.c
ed1787d
+++ b/grub-core/font/font.c
ed1787d
@@ -1203,12 +1203,12 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
ed1787d
   ctx.bounds.height = main_glyph->height;
ed1787d
 
ed1787d
   above_rightx = main_glyph->offset_x + main_glyph->width;
ed1787d
-  above_righty = ctx.bounds.y + ctx.bounds.height;
ed1787d
+  above_righty = ctx.bounds.y + (int) ctx.bounds.height;
ed1787d
 
ed1787d
   above_leftx = main_glyph->offset_x;
ed1787d
-  above_lefty = ctx.bounds.y + ctx.bounds.height;
ed1787d
+  above_lefty = ctx.bounds.y + (int) ctx.bounds.height;
ed1787d
 
ed1787d
-  below_rightx = ctx.bounds.x + ctx.bounds.width;
ed1787d
+  below_rightx = ctx.bounds.x + (int) ctx.bounds.width;
ed1787d
   below_righty = ctx.bounds.y;
ed1787d
 
ed1787d
   comb = grub_unicode_get_comb (glyph_id);
ed1787d
@@ -1221,7 +1221,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
ed1787d
 
ed1787d
       if (!combining_glyphs[i])
ed1787d
 	continue;
ed1787d
-      targetx = (ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x;
ed1787d
+      targetx = ((int) ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x;
ed1787d
       /* CGJ is to avoid diacritics reordering. */
ed1787d
       if (comb[i].code
ed1787d
 	  == GRUB_UNICODE_COMBINING_GRAPHEME_JOINER)
ed1787d
@@ -1231,8 +1231,8 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
ed1787d
 	case GRUB_UNICODE_COMB_OVERLAY:
ed1787d
 	  do_blit (combining_glyphs[i],
ed1787d
 		   targetx,
ed1787d
-		   (ctx.bounds.height - combining_glyphs[i]->height) / 2
ed1787d
-		   - (ctx.bounds.height + ctx.bounds.y), &ctx;;
ed1787d
+		   ((int) ctx.bounds.height - combining_glyphs[i]->height) / 2
ed1787d
+		   - ((int) ctx.bounds.height + ctx.bounds.y), &ctx;;
ed1787d
 	  if (min_devwidth < combining_glyphs[i]->width)
ed1787d
 	    min_devwidth = combining_glyphs[i]->width;
ed1787d
 	  break;
ed1787d
@@ -1305,7 +1305,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
ed1787d
 	  /* Fallthrough.  */
ed1787d
 	case GRUB_UNICODE_STACK_ATTACHED_ABOVE:
ed1787d
 	  do_blit (combining_glyphs[i], targetx,
ed1787d
-		   -(ctx.bounds.height + ctx.bounds.y + space
ed1787d
+		   -((int) ctx.bounds.height + ctx.bounds.y + space
ed1787d
 		     + combining_glyphs[i]->height), &ctx;;
ed1787d
 	  if (min_devwidth < combining_glyphs[i]->width)
ed1787d
 	    min_devwidth = combining_glyphs[i]->width;
ed1787d
@@ -1313,7 +1313,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id,
ed1787d
 
ed1787d
 	case GRUB_UNICODE_COMB_HEBREW_DAGESH:
ed1787d
 	  do_blit (combining_glyphs[i], targetx,
ed1787d
-		   -(ctx.bounds.height / 2 + ctx.bounds.y
ed1787d
+		   -((int) ctx.bounds.height / 2 + ctx.bounds.y
ed1787d
 		     + combining_glyphs[i]->height / 2), &ctx;;
ed1787d
 	  if (min_devwidth < combining_glyphs[i]->width)
ed1787d
 	    min_devwidth = combining_glyphs[i]->width;