1From fdbe7209152ad6f09a1166f64f162017f2145ba3 Mon Sep 17 00:00:00 2001 2From: Zhang Boyang <zhangboyang.id@gmail.com> 3Date: Mon, 24 Oct 2022 08:05:35 +0800 4Subject: [PATCH] font: Fix an integer underflow in blit_comb() 5 6The expression (ctx.bounds.height - combining_glyphs[i]->height) / 2 may 7evaluate to a very big invalid value even if both ctx.bounds.height and 8combining_glyphs[i]->height are small integers. For example, if 9ctx.bounds.height is 10 and combining_glyphs[i]->height is 12, this 10expression evaluates to 2147483647 (expected -1). This is because 11coordinates are allowed to be negative but ctx.bounds.height is an 12unsigned int. So, the subtraction operates on unsigned ints and 13underflows to a very big value. The division makes things even worse. 14The quotient is still an invalid value even if converted back to int. 15 16This patch fixes the problem by casting ctx.bounds.height to int. As 17a result the subtraction will operate on int and grub_uint16_t which 18will be promoted to an int. So, the underflow will no longer happen. Other 19uses of ctx.bounds.height (and ctx.bounds.width) are also casted to int, 20to ensure coordinates are always calculated on signed integers. 21 22Fixes: CVE-2022-3775 23 24Reported-by: Daniel Axtens <dja@axtens.net> 25Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com> 26Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> 27 28Upstream-Status: Backport from 29[https://git.savannah.gnu.org/cgit/grub.git/commit/?id=992c06191babc1e109caf40d6a07ec6fdef427af] 30CVE: CVE-2022-3775 31 32Signed-off-by: Xiangyu Chen <xiangyu.chen@windriver.com> 33 34--- 35 grub-core/font/font.c | 16 ++++++++-------- 36 1 file changed, 8 insertions(+), 8 deletions(-) 37 38diff --git a/grub-core/font/font.c b/grub-core/font/font.c 39index 0ff5525..7b1cbde 100644 40--- a/grub-core/font/font.c 41+++ b/grub-core/font/font.c 42@@ -1206,12 +1206,12 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, 43 ctx.bounds.height = main_glyph->height; 44 45 above_rightx = main_glyph->offset_x + main_glyph->width; 46- above_righty = ctx.bounds.y + ctx.bounds.height; 47+ above_righty = ctx.bounds.y + (int) ctx.bounds.height; 48 49 above_leftx = main_glyph->offset_x; 50- above_lefty = ctx.bounds.y + ctx.bounds.height; 51+ above_lefty = ctx.bounds.y + (int) ctx.bounds.height; 52 53- below_rightx = ctx.bounds.x + ctx.bounds.width; 54+ below_rightx = ctx.bounds.x + (int) ctx.bounds.width; 55 below_righty = ctx.bounds.y; 56 57 comb = grub_unicode_get_comb (glyph_id); 58@@ -1224,7 +1224,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, 59 60 if (!combining_glyphs[i]) 61 continue; 62- targetx = (ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x; 63+ targetx = ((int) ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x; 64 /* CGJ is to avoid diacritics reordering. */ 65 if (comb[i].code 66 == GRUB_UNICODE_COMBINING_GRAPHEME_JOINER) 67@@ -1234,8 +1234,8 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, 68 case GRUB_UNICODE_COMB_OVERLAY: 69 do_blit (combining_glyphs[i], 70 targetx, 71- (ctx.bounds.height - combining_glyphs[i]->height) / 2 72- - (ctx.bounds.height + ctx.bounds.y), &ctx); 73+ ((int) ctx.bounds.height - combining_glyphs[i]->height) / 2 74+ - ((int) ctx.bounds.height + ctx.bounds.y), &ctx); 75 if (min_devwidth < combining_glyphs[i]->width) 76 min_devwidth = combining_glyphs[i]->width; 77 break; 78@@ -1308,7 +1308,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, 79 /* Fallthrough. */ 80 case GRUB_UNICODE_STACK_ATTACHED_ABOVE: 81 do_blit (combining_glyphs[i], targetx, 82- -(ctx.bounds.height + ctx.bounds.y + space 83+ -((int) ctx.bounds.height + ctx.bounds.y + space 84 + combining_glyphs[i]->height), &ctx); 85 if (min_devwidth < combining_glyphs[i]->width) 86 min_devwidth = combining_glyphs[i]->width; 87@@ -1316,7 +1316,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, 88 89 case GRUB_UNICODE_COMB_HEBREW_DAGESH: 90 do_blit (combining_glyphs[i], targetx, 91- -(ctx.bounds.height / 2 + ctx.bounds.y 92+ -((int) ctx.bounds.height / 2 + ctx.bounds.y 93 + combining_glyphs[i]->height / 2), &ctx); 94 if (min_devwidth < combining_glyphs[i]->width) 95 min_devwidth = combining_glyphs[i]->width; 96