From fdbe7209152ad6f09a1166f64f162017f2145ba3 Mon Sep 17 00:00:00 2001 From: Zhang Boyang Date: Mon, 24 Oct 2022 08:05:35 +0800 Subject: [PATCH] font: Fix an integer underflow in blit_comb() The expression (ctx.bounds.height - combining_glyphs[i]->height) / 2 may evaluate to a very big invalid value even if both ctx.bounds.height and combining_glyphs[i]->height are small integers. For example, if ctx.bounds.height is 10 and combining_glyphs[i]->height is 12, this expression evaluates to 2147483647 (expected -1). This is because coordinates are allowed to be negative but ctx.bounds.height is an unsigned int. So, the subtraction operates on unsigned ints and underflows to a very big value. The division makes things even worse. The quotient is still an invalid value even if converted back to int. This patch fixes the problem by casting ctx.bounds.height to int. As a result the subtraction will operate on int and grub_uint16_t which will be promoted to an int. So, the underflow will no longer happen. Other uses of ctx.bounds.height (and ctx.bounds.width) are also casted to int, to ensure coordinates are always calculated on signed integers. Fixes: CVE-2022-3775 Reported-by: Daniel Axtens Signed-off-by: Zhang Boyang Reviewed-by: Daniel Kiper Signed-off-by: Xiangyu Chen Upstream-Status: Backport [https://git.savannah.gnu.org/cgit/grub.git/commit/?id=992c06191babc1e109caf40d6a07ec6fdef427af] CVE: CVE-2022-3775 Signed-off-by: Hitendra Prajapati --- grub-core/font/font.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/grub-core/font/font.c b/grub-core/font/font.c index f110db9..3b76b22 100644 --- a/grub-core/font/font.c +++ b/grub-core/font/font.c @@ -1200,12 +1200,12 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, ctx.bounds.height = main_glyph->height; above_rightx = main_glyph->offset_x + main_glyph->width; - above_righty = ctx.bounds.y + ctx.bounds.height; + above_righty = ctx.bounds.y + (int) ctx.bounds.height; above_leftx = main_glyph->offset_x; - above_lefty = ctx.bounds.y + ctx.bounds.height; + above_lefty = ctx.bounds.y + (int) ctx.bounds.height; - below_rightx = ctx.bounds.x + ctx.bounds.width; + below_rightx = ctx.bounds.x + (int) ctx.bounds.width; below_righty = ctx.bounds.y; comb = grub_unicode_get_comb (glyph_id); @@ -1218,7 +1218,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, if (!combining_glyphs[i]) continue; - targetx = (ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x; + targetx = ((int) ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x; /* CGJ is to avoid diacritics reordering. */ if (comb[i].code == GRUB_UNICODE_COMBINING_GRAPHEME_JOINER) @@ -1228,8 +1228,8 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, case GRUB_UNICODE_COMB_OVERLAY: do_blit (combining_glyphs[i], targetx, - (ctx.bounds.height - combining_glyphs[i]->height) / 2 - - (ctx.bounds.height + ctx.bounds.y), &ctx); + ((int) ctx.bounds.height - combining_glyphs[i]->height) / 2 + - ((int) ctx.bounds.height + ctx.bounds.y), &ctx); if (min_devwidth < combining_glyphs[i]->width) min_devwidth = combining_glyphs[i]->width; break; @@ -1302,7 +1302,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, /* Fallthrough. */ case GRUB_UNICODE_STACK_ATTACHED_ABOVE: do_blit (combining_glyphs[i], targetx, - -(ctx.bounds.height + ctx.bounds.y + space + -((int) ctx.bounds.height + ctx.bounds.y + space + combining_glyphs[i]->height), &ctx); if (min_devwidth < combining_glyphs[i]->width) min_devwidth = combining_glyphs[i]->width; @@ -1310,7 +1310,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, case GRUB_UNICODE_COMB_HEBREW_DAGESH: do_blit (combining_glyphs[i], targetx, - -(ctx.bounds.height / 2 + ctx.bounds.y + -((int) ctx.bounds.height / 2 + ctx.bounds.y + combining_glyphs[i]->height / 2), &ctx); if (min_devwidth < combining_glyphs[i]->width) min_devwidth = combining_glyphs[i]->width; -- 2.25.1