| From fdbe7209152ad6f09a1166f64f162017f2145ba3 Mon Sep 17 00:00:00 2001 |
| From: Zhang Boyang <zhangboyang.id@gmail.com> |
| 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 <dja@axtens.net> |
| Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com> |
| Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> |
| |
| Upstream-Status: Backport from |
| [https://git.savannah.gnu.org/cgit/grub.git/commit/?id=992c06191babc1e109caf40d6a07ec6fdef427af] |
| CVE: CVE-2022-3775 |
| |
| Signed-off-by: Xiangyu Chen <xiangyu.chen@windriver.com> |
| |
| --- |
| 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 0ff5525..7b1cbde 100644 |
| --- a/grub-core/font/font.c |
| +++ b/grub-core/font/font.c |
| @@ -1206,12 +1206,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); |
| @@ -1224,7 +1224,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) |
| @@ -1234,8 +1234,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; |
| @@ -1308,7 +1308,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; |
| @@ -1316,7 +1316,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; |