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