Andrew Geissler | 517393d | 2023-01-13 08:55:19 -0600 | [diff] [blame] | 1 | From fdbe7209152ad6f09a1166f64f162017f2145ba3 Mon Sep 17 00:00:00 2001 |
| 2 | From: Zhang Boyang <zhangboyang.id@gmail.com> |
| 3 | Date: Mon, 24 Oct 2022 08:05:35 +0800 |
| 4 | Subject: [PATCH] font: Fix an integer underflow in blit_comb() |
| 5 | |
| 6 | The expression (ctx.bounds.height - combining_glyphs[i]->height) / 2 may |
| 7 | evaluate to a very big invalid value even if both ctx.bounds.height and |
| 8 | combining_glyphs[i]->height are small integers. For example, if |
| 9 | ctx.bounds.height is 10 and combining_glyphs[i]->height is 12, this |
| 10 | expression evaluates to 2147483647 (expected -1). This is because |
| 11 | coordinates are allowed to be negative but ctx.bounds.height is an |
| 12 | unsigned int. So, the subtraction operates on unsigned ints and |
| 13 | underflows to a very big value. The division makes things even worse. |
| 14 | The quotient is still an invalid value even if converted back to int. |
| 15 | |
| 16 | This patch fixes the problem by casting ctx.bounds.height to int. As |
| 17 | a result the subtraction will operate on int and grub_uint16_t which |
| 18 | will be promoted to an int. So, the underflow will no longer happen. Other |
| 19 | uses of ctx.bounds.height (and ctx.bounds.width) are also casted to int, |
| 20 | to ensure coordinates are always calculated on signed integers. |
| 21 | |
| 22 | Fixes: CVE-2022-3775 |
| 23 | |
| 24 | Reported-by: Daniel Axtens <dja@axtens.net> |
| 25 | Signed-off-by: Zhang Boyang <zhangboyang.id@gmail.com> |
| 26 | Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> |
| 27 | |
| 28 | Upstream-Status: Backport from |
| 29 | [https://git.savannah.gnu.org/cgit/grub.git/commit/?id=992c06191babc1e109caf40d6a07ec6fdef427af] |
| 30 | CVE: CVE-2022-3775 |
| 31 | |
| 32 | Signed-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 | |
| 38 | diff --git a/grub-core/font/font.c b/grub-core/font/font.c |
| 39 | index 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; |