1From 4ad7e85adc3803788d65707a9db11fd681aebe4a Mon Sep 17 00:00:00 2001 2From: Peter Jones <pjones@redhat.com> 3Date: Mon, 15 Jun 2020 12:28:27 -0400 4Subject: [PATCH] malloc: Use overflow checking primitives where we do 5 complex allocations 6MIME-Version: 1.0 7Content-Type: text/plain; charset=UTF-8 8Content-Transfer-Encoding: 8bit 9 10This attempts to fix the places where we do the following where 11arithmetic_expr may include unvalidated data: 12 13 X = grub_malloc(arithmetic_expr); 14 15It accomplishes this by doing the arithmetic ahead of time using grub_add(), 16grub_sub(), grub_mul() and testing for overflow before proceeding. 17 18Among other issues, this fixes: 19 - allocation of integer overflow in grub_video_bitmap_create() 20 reported by Chris Coulson, 21 - allocation of integer overflow in grub_png_decode_image_header() 22 reported by Chris Coulson, 23 - allocation of integer overflow in grub_squash_read_symlink() 24 reported by Chris Coulson, 25 - allocation of integer overflow in grub_ext2_read_symlink() 26 reported by Chris Coulson, 27 - allocation of integer overflow in read_section_as_string() 28 reported by Chris Coulson. 29 30Fixes: CVE-2020-14309, CVE-2020-14310, CVE-2020-14311 31 32Signed-off-by: Peter Jones <pjones@redhat.com> 33Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> 34Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com> 35--- 36 grub-core/commands/legacycfg.c | 29 +++++++++++++++---- 37 grub-core/commands/wildcard.c | 36 ++++++++++++++++++++---- 38 grub-core/disk/ldm.c | 32 +++++++++++++++------ 39 grub-core/font/font.c | 7 ++++- 40 grub-core/fs/btrfs.c | 28 +++++++++++++------ 41 grub-core/fs/ext2.c | 10 ++++++- 42 grub-core/fs/iso9660.c | 51 ++++++++++++++++++++++++---------- 43 grub-core/fs/sfs.c | 27 ++++++++++++++---- 44 grub-core/fs/squash4.c | 45 ++++++++++++++++++++++-------- 45 grub-core/fs/udf.c | 41 +++++++++++++++++---------- 46 grub-core/fs/xfs.c | 11 +++++--- 47 grub-core/fs/zfs/zfs.c | 22 ++++++++++----- 48 grub-core/fs/zfs/zfscrypt.c | 7 ++++- 49 grub-core/lib/arg.c | 20 +++++++++++-- 50 grub-core/loader/i386/bsd.c | 8 +++++- 51 grub-core/net/dns.c | 9 +++++- 52 grub-core/normal/charset.c | 10 +++++-- 53 grub-core/normal/cmdline.c | 14 ++++++++-- 54 grub-core/normal/menu_entry.c | 13 +++++++-- 55 grub-core/script/argv.c | 16 +++++++++-- 56 grub-core/script/lexer.c | 21 ++++++++++++-- 57 grub-core/video/bitmap.c | 25 +++++++++++------ 58 grub-core/video/readers/png.c | 13 +++++++-- 59 23 files changed, 382 insertions(+), 113 deletions(-) 60 61diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c 62index 5e3ec0d5e..cc5971f4d 100644 63--- a/grub-core/commands/legacycfg.c 64+++ b/grub-core/commands/legacycfg.c 65@@ -32,6 +32,7 @@ 66 #include <grub/auth.h> 67 #include <grub/disk.h> 68 #include <grub/partition.h> 69+#include <grub/safemath.h> 70 71 GRUB_MOD_LICENSE ("GPLv3+"); 72 73@@ -104,13 +105,22 @@ legacy_file (const char *filename) 74 if (newsuffix) 75 { 76 char *t; 77- 78+ grub_size_t sz; 79+ 80+ if (grub_add (grub_strlen (suffix), grub_strlen (newsuffix), &sz) || 81+ grub_add (sz, 1, &sz)) 82+ { 83+ grub_errno = GRUB_ERR_OUT_OF_RANGE; 84+ goto fail_0; 85+ } 86+ 87 t = suffix; 88- suffix = grub_realloc (suffix, grub_strlen (suffix) 89- + grub_strlen (newsuffix) + 1); 90+ suffix = grub_realloc (suffix, sz); 91 if (!suffix) 92 { 93 grub_free (t); 94+ 95+ fail_0: 96 grub_free (entrysrc); 97 grub_free (parsed); 98 grub_free (newsuffix); 99@@ -154,13 +164,22 @@ legacy_file (const char *filename) 100 else 101 { 102 char *t; 103+ grub_size_t sz; 104+ 105+ if (grub_add (grub_strlen (entrysrc), grub_strlen (parsed), &sz) || 106+ grub_add (sz, 1, &sz)) 107+ { 108+ grub_errno = GRUB_ERR_OUT_OF_RANGE; 109+ goto fail_1; 110+ } 111 112 t = entrysrc; 113- entrysrc = grub_realloc (entrysrc, grub_strlen (entrysrc) 114- + grub_strlen (parsed) + 1); 115+ entrysrc = grub_realloc (entrysrc, sz); 116 if (!entrysrc) 117 { 118 grub_free (t); 119+ 120+ fail_1: 121 grub_free (parsed); 122 grub_free (suffix); 123 return grub_errno; 124diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c 125index 4a106ca04..cc3290311 100644 126--- a/grub-core/commands/wildcard.c 127+++ b/grub-core/commands/wildcard.c 128@@ -23,6 +23,7 @@ 129 #include <grub/file.h> 130 #include <grub/device.h> 131 #include <grub/script_sh.h> 132+#include <grub/safemath.h> 133 134 #include <regex.h> 135 136@@ -48,6 +49,7 @@ merge (char **dest, char **ps) 137 int i; 138 int j; 139 char **p; 140+ grub_size_t sz; 141 142 if (! dest) 143 return ps; 144@@ -60,7 +62,12 @@ merge (char **dest, char **ps) 145 for (j = 0; ps[j]; j++) 146 ; 147 148- p = grub_realloc (dest, sizeof (char*) * (i + j + 1)); 149+ if (grub_add (i, j, &sz) || 150+ grub_add (sz, 1, &sz) || 151+ grub_mul (sz, sizeof (char *), &sz)) 152+ return dest; 153+ 154+ p = grub_realloc (dest, sz); 155 if (! p) 156 { 157 grub_free (dest); 158@@ -115,8 +122,15 @@ make_regex (const char *start, const char *end, regex_t *regexp) 159 char ch; 160 int i = 0; 161 unsigned len = end - start; 162- char *buffer = grub_malloc (len * 2 + 2 + 1); /* worst case size. */ 163+ char *buffer; 164+ grub_size_t sz; 165 166+ /* Worst case size is (len * 2 + 2 + 1). */ 167+ if (grub_mul (len, 2, &sz) || 168+ grub_add (sz, 3, &sz)) 169+ return 1; 170+ 171+ buffer = grub_malloc (sz); 172 if (! buffer) 173 return 1; 174 175@@ -226,6 +240,7 @@ match_devices_iter (const char *name, void *data) 176 struct match_devices_ctx *ctx = data; 177 char **t; 178 char *buffer; 179+ grub_size_t sz; 180 181 /* skip partitions if asked to. */ 182 if (ctx->noparts && grub_strchr (name, ',')) 183@@ -239,11 +254,16 @@ match_devices_iter (const char *name, void *data) 184 if (regexec (ctx->regexp, buffer, 0, 0, 0)) 185 { 186 grub_dprintf ("expand", "not matched\n"); 187+ fail: 188 grub_free (buffer); 189 return 0; 190 } 191 192- t = grub_realloc (ctx->devs, sizeof (char*) * (ctx->ndev + 2)); 193+ if (grub_add (ctx->ndev, 2, &sz) || 194+ grub_mul (sz, sizeof (char *), &sz)) 195+ goto fail; 196+ 197+ t = grub_realloc (ctx->devs, sz); 198 if (! t) 199 { 200 grub_free (buffer); 201@@ -300,6 +320,7 @@ match_files_iter (const char *name, 202 struct match_files_ctx *ctx = data; 203 char **t; 204 char *buffer; 205+ grub_size_t sz; 206 207 /* skip . and .. names */ 208 if (grub_strcmp(".", name) == 0 || grub_strcmp("..", name) == 0) 209@@ -315,9 +336,14 @@ match_files_iter (const char *name, 210 if (! buffer) 211 return 1; 212 213- t = grub_realloc (ctx->files, sizeof (char*) * (ctx->nfile + 2)); 214- if (! t) 215+ if (grub_add (ctx->nfile, 2, &sz) || 216+ grub_mul (sz, sizeof (char *), &sz)) 217+ goto fail; 218+ 219+ t = grub_realloc (ctx->files, sz); 220+ if (!t) 221 { 222+ fail: 223 grub_free (buffer); 224 return 1; 225 } 226diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c 227index e6323701a..58f8a53e1 100644 228--- a/grub-core/disk/ldm.c 229+++ b/grub-core/disk/ldm.c 230@@ -25,6 +25,7 @@ 231 #include <grub/msdos_partition.h> 232 #include <grub/gpt_partition.h> 233 #include <grub/i18n.h> 234+#include <grub/safemath.h> 235 236 #ifdef GRUB_UTIL 237 #include <grub/emu/misc.h> 238@@ -289,6 +290,7 @@ make_vg (grub_disk_t disk, 239 struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE 240 / sizeof (struct grub_ldm_vblk)]; 241 unsigned i; 242+ grub_size_t sz; 243 err = grub_disk_read (disk, cursec, 0, 244 sizeof(vblk), &vblk); 245 if (err) 246@@ -350,7 +352,13 @@ make_vg (grub_disk_t disk, 247 grub_free (lv); 248 goto fail2; 249 } 250- lv->name = grub_malloc (*ptr + 1); 251+ if (grub_add (*ptr, 1, &sz)) 252+ { 253+ grub_free (lv->internal_id); 254+ grub_free (lv); 255+ goto fail2; 256+ } 257+ lv->name = grub_malloc (sz); 258 if (!lv->name) 259 { 260 grub_free (lv->internal_id); 261@@ -599,10 +607,13 @@ make_vg (grub_disk_t disk, 262 if (lv->segments->node_alloc == lv->segments->node_count) 263 { 264 void *t; 265- lv->segments->node_alloc *= 2; 266- t = grub_realloc (lv->segments->nodes, 267- sizeof (*lv->segments->nodes) 268- * lv->segments->node_alloc); 269+ grub_size_t sz; 270+ 271+ if (grub_mul (lv->segments->node_alloc, 2, &lv->segments->node_alloc) || 272+ grub_mul (lv->segments->node_alloc, sizeof (*lv->segments->nodes), &sz)) 273+ goto fail2; 274+ 275+ t = grub_realloc (lv->segments->nodes, sz); 276 if (!t) 277 goto fail2; 278 lv->segments->nodes = t; 279@@ -723,10 +734,13 @@ make_vg (grub_disk_t disk, 280 if (comp->segment_alloc == comp->segment_count) 281 { 282 void *t; 283- comp->segment_alloc *= 2; 284- t = grub_realloc (comp->segments, 285- comp->segment_alloc 286- * sizeof (*comp->segments)); 287+ grub_size_t sz; 288+ 289+ if (grub_mul (comp->segment_alloc, 2, &comp->segment_alloc) || 290+ grub_mul (comp->segment_alloc, sizeof (*comp->segments), &sz)) 291+ goto fail2; 292+ 293+ t = grub_realloc (comp->segments, sz); 294 if (!t) 295 goto fail2; 296 comp->segments = t; 297diff --git a/grub-core/font/font.c b/grub-core/font/font.c 298index 8e118b315..5edb477ac 100644 299--- a/grub-core/font/font.c 300+++ b/grub-core/font/font.c 301@@ -30,6 +30,7 @@ 302 #include <grub/unicode.h> 303 #include <grub/fontformat.h> 304 #include <grub/env.h> 305+#include <grub/safemath.h> 306 307 GRUB_MOD_LICENSE ("GPLv3+"); 308 309@@ -360,9 +361,13 @@ static char * 310 read_section_as_string (struct font_file_section *section) 311 { 312 char *str; 313+ grub_size_t sz; 314 grub_ssize_t ret; 315 316- str = grub_malloc (section->length + 1); 317+ if (grub_add (section->length, 1, &sz)) 318+ return NULL; 319+ 320+ str = grub_malloc (sz); 321 if (!str) 322 return 0; 323 324diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c 325index 11272efc1..2b65bd56a 100644 326--- a/grub-core/fs/btrfs.c 327+++ b/grub-core/fs/btrfs.c 328@@ -40,6 +40,7 @@ 329 #include <grub/btrfs.h> 330 #include <grub/crypto.h> 331 #include <grub/diskfilter.h> 332+#include <grub/safemath.h> 333 334 GRUB_MOD_LICENSE ("GPLv3+"); 335 336@@ -329,9 +330,13 @@ save_ref (struct grub_btrfs_leaf_descriptor *desc, 337 if (desc->allocated < desc->depth) 338 { 339 void *newdata; 340- desc->allocated *= 2; 341- newdata = grub_realloc (desc->data, sizeof (desc->data[0]) 342- * desc->allocated); 343+ grub_size_t sz; 344+ 345+ if (grub_mul (desc->allocated, 2, &desc->allocated) || 346+ grub_mul (desc->allocated, sizeof (desc->data[0]), &sz)) 347+ return GRUB_ERR_OUT_OF_RANGE; 348+ 349+ newdata = grub_realloc (desc->data, sz); 350 if (!newdata) 351 return grub_errno; 352 desc->data = newdata; 353@@ -622,16 +627,21 @@ find_device (struct grub_btrfs_data *data, grub_uint64_t id) 354 if (data->n_devices_attached > data->n_devices_allocated) 355 { 356 void *tmp; 357- data->n_devices_allocated = 2 * data->n_devices_attached + 1; 358- data->devices_attached 359- = grub_realloc (tmp = data->devices_attached, 360- data->n_devices_allocated 361- * sizeof (data->devices_attached[0])); 362+ grub_size_t sz; 363+ 364+ if (grub_mul (data->n_devices_attached, 2, &data->n_devices_allocated) || 365+ grub_add (data->n_devices_allocated, 1, &data->n_devices_allocated) || 366+ grub_mul (data->n_devices_allocated, sizeof (data->devices_attached[0]), &sz)) 367+ goto fail; 368+ 369+ data->devices_attached = grub_realloc (tmp = data->devices_attached, sz); 370 if (!data->devices_attached) 371 { 372+ data->devices_attached = tmp; 373+ 374+ fail: 375 if (ctx.dev_found) 376 grub_device_close (ctx.dev_found); 377- data->devices_attached = tmp; 378 return NULL; 379 } 380 } 381diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c 382index 9b389802a..ac33bcd68 100644 383--- a/grub-core/fs/ext2.c 384+++ b/grub-core/fs/ext2.c 385@@ -46,6 +46,7 @@ 386 #include <grub/dl.h> 387 #include <grub/types.h> 388 #include <grub/fshelp.h> 389+#include <grub/safemath.h> 390 391 GRUB_MOD_LICENSE ("GPLv3+"); 392 393@@ -703,6 +704,7 @@ grub_ext2_read_symlink (grub_fshelp_node_t node) 394 { 395 char *symlink; 396 struct grub_fshelp_node *diro = node; 397+ grub_size_t sz; 398 399 if (! diro->inode_read) 400 { 401@@ -717,7 +719,13 @@ grub_ext2_read_symlink (grub_fshelp_node_t node) 402 } 403 } 404 405- symlink = grub_malloc (grub_le_to_cpu32 (diro->inode.size) + 1); 406+ if (grub_add (grub_le_to_cpu32 (diro->inode.size), 1, &sz)) 407+ { 408+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); 409+ return NULL; 410+ } 411+ 412+ symlink = grub_malloc (sz); 413 if (! symlink) 414 return 0; 415 416diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c 417index 4f1b52a55..7ba5b300b 100644 418--- a/grub-core/fs/iso9660.c 419+++ b/grub-core/fs/iso9660.c 420@@ -28,6 +28,7 @@ 421 #include <grub/fshelp.h> 422 #include <grub/charset.h> 423 #include <grub/datetime.h> 424+#include <grub/safemath.h> 425 426 GRUB_MOD_LICENSE ("GPLv3+"); 427 428@@ -531,8 +532,13 @@ add_part (struct iterate_dir_ctx *ctx, 429 int len2) 430 { 431 int size = ctx->symlink ? grub_strlen (ctx->symlink) : 0; 432+ grub_size_t sz; 433 434- ctx->symlink = grub_realloc (ctx->symlink, size + len2 + 1); 435+ if (grub_add (size, len2, &sz) || 436+ grub_add (sz, 1, &sz)) 437+ return; 438+ 439+ ctx->symlink = grub_realloc (ctx->symlink, sz); 440 if (! ctx->symlink) 441 return; 442 443@@ -560,17 +566,24 @@ susp_iterate_dir (struct grub_iso9660_susp_entry *entry, 444 { 445 grub_size_t off = 0, csize = 1; 446 char *old; 447+ grub_size_t sz; 448+ 449 csize = entry->len - 5; 450 old = ctx->filename; 451 if (ctx->filename_alloc) 452 { 453 off = grub_strlen (ctx->filename); 454- ctx->filename = grub_realloc (ctx->filename, csize + off + 1); 455+ if (grub_add (csize, off, &sz) || 456+ grub_add (sz, 1, &sz)) 457+ return GRUB_ERR_OUT_OF_RANGE; 458+ ctx->filename = grub_realloc (ctx->filename, sz); 459 } 460 else 461 { 462 off = 0; 463- ctx->filename = grub_zalloc (csize + 1); 464+ if (grub_add (csize, 1, &sz)) 465+ return GRUB_ERR_OUT_OF_RANGE; 466+ ctx->filename = grub_zalloc (sz); 467 } 468 if (!ctx->filename) 469 { 470@@ -776,14 +789,18 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, 471 if (node->have_dirents >= node->alloc_dirents) 472 { 473 struct grub_fshelp_node *new_node; 474- node->alloc_dirents *= 2; 475- new_node = grub_realloc (node, 476- sizeof (struct grub_fshelp_node) 477- + ((node->alloc_dirents 478- - ARRAY_SIZE (node->dirents)) 479- * sizeof (node->dirents[0]))); 480+ grub_size_t sz; 481+ 482+ if (grub_mul (node->alloc_dirents, 2, &node->alloc_dirents) || 483+ grub_sub (node->alloc_dirents, ARRAY_SIZE (node->dirents), &sz) || 484+ grub_mul (sz, sizeof (node->dirents[0]), &sz) || 485+ grub_add (sz, sizeof (struct grub_fshelp_node), &sz)) 486+ goto fail_0; 487+ 488+ new_node = grub_realloc (node, sz); 489 if (!new_node) 490 { 491+ fail_0: 492 if (ctx.filename_alloc) 493 grub_free (ctx.filename); 494 grub_free (node); 495@@ -799,14 +816,18 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, 496 * sizeof (node->dirents[0]) < grub_strlen (ctx.symlink) + 1) 497 { 498 struct grub_fshelp_node *new_node; 499- new_node = grub_realloc (node, 500- sizeof (struct grub_fshelp_node) 501- + ((node->alloc_dirents 502- - ARRAY_SIZE (node->dirents)) 503- * sizeof (node->dirents[0])) 504- + grub_strlen (ctx.symlink) + 1); 505+ grub_size_t sz; 506+ 507+ if (grub_sub (node->alloc_dirents, ARRAY_SIZE (node->dirents), &sz) || 508+ grub_mul (sz, sizeof (node->dirents[0]), &sz) || 509+ grub_add (sz, sizeof (struct grub_fshelp_node) + 1, &sz) || 510+ grub_add (sz, grub_strlen (ctx.symlink), &sz)) 511+ goto fail_1; 512+ 513+ new_node = grub_realloc (node, sz); 514 if (!new_node) 515 { 516+ fail_1: 517 if (ctx.filename_alloc) 518 grub_free (ctx.filename); 519 grub_free (node); 520diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c 521index 90f7fb379..de2b107a4 100644 522--- a/grub-core/fs/sfs.c 523+++ b/grub-core/fs/sfs.c 524@@ -26,6 +26,7 @@ 525 #include <grub/types.h> 526 #include <grub/fshelp.h> 527 #include <grub/charset.h> 528+#include <grub/safemath.h> 529 530 GRUB_MOD_LICENSE ("GPLv3+"); 531 532@@ -307,10 +308,15 @@ grub_sfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) 533 if (node->cache && node->cache_size >= node->cache_allocated) 534 { 535 struct cache_entry *e = node->cache; 536- e = grub_realloc (node->cache,node->cache_allocated * 2 537- * sizeof (e[0])); 538+ grub_size_t sz; 539+ 540+ if (grub_mul (node->cache_allocated, 2 * sizeof (e[0]), &sz)) 541+ goto fail; 542+ 543+ e = grub_realloc (node->cache, sz); 544 if (!e) 545 { 546+ fail: 547 grub_errno = 0; 548 grub_free (node->cache); 549 node->cache = 0; 550@@ -477,10 +483,16 @@ grub_sfs_create_node (struct grub_fshelp_node **node, 551 grub_size_t len = grub_strlen (name); 552 grub_uint8_t *name_u8; 553 int ret; 554+ grub_size_t sz; 555+ 556+ if (grub_mul (len, GRUB_MAX_UTF8_PER_LATIN1, &sz) || 557+ grub_add (sz, 1, &sz)) 558+ return 1; 559+ 560 *node = grub_malloc (sizeof (**node)); 561 if (!*node) 562 return 1; 563- name_u8 = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1); 564+ name_u8 = grub_malloc (sz); 565 if (!name_u8) 566 { 567 grub_free (*node); 568@@ -724,8 +736,13 @@ grub_sfs_label (grub_device_t device, char **label) 569 data = grub_sfs_mount (disk); 570 if (data) 571 { 572- grub_size_t len = grub_strlen (data->label); 573- *label = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1); 574+ grub_size_t sz, len = grub_strlen (data->label); 575+ 576+ if (grub_mul (len, GRUB_MAX_UTF8_PER_LATIN1, &sz) || 577+ grub_add (sz, 1, &sz)) 578+ return GRUB_ERR_OUT_OF_RANGE; 579+ 580+ *label = grub_malloc (sz); 581 if (*label) 582 *grub_latin1_to_utf8 ((grub_uint8_t *) *label, 583 (const grub_uint8_t *) data->label, 584diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c 585index 95d5c1e1f..785123894 100644 586--- a/grub-core/fs/squash4.c 587+++ b/grub-core/fs/squash4.c 588@@ -26,6 +26,7 @@ 589 #include <grub/types.h> 590 #include <grub/fshelp.h> 591 #include <grub/deflate.h> 592+#include <grub/safemath.h> 593 #include <minilzo.h> 594 595 #include "xz.h" 596@@ -459,7 +460,17 @@ grub_squash_read_symlink (grub_fshelp_node_t node) 597 { 598 char *ret; 599 grub_err_t err; 600- ret = grub_malloc (grub_le_to_cpu32 (node->ino.symlink.namelen) + 1); 601+ grub_size_t sz; 602+ 603+ if (grub_add (grub_le_to_cpu32 (node->ino.symlink.namelen), 1, &sz)) 604+ { 605+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); 606+ return NULL; 607+ } 608+ 609+ ret = grub_malloc (sz); 610+ if (!ret) 611+ return NULL; 612 613 err = read_chunk (node->data, ret, 614 grub_le_to_cpu32 (node->ino.symlink.namelen), 615@@ -506,11 +517,16 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, 616 617 { 618 grub_fshelp_node_t node; 619- node = grub_malloc (sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); 620+ grub_size_t sz; 621+ 622+ if (grub_mul (dir->stsize, sizeof (dir->stack[0]), &sz) || 623+ grub_add (sz, sizeof (*node), &sz)) 624+ return 0; 625+ 626+ node = grub_malloc (sz); 627 if (!node) 628 return 0; 629- grub_memcpy (node, dir, 630- sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); 631+ grub_memcpy (node, dir, sz); 632 if (hook (".", GRUB_FSHELP_DIR, node, hook_data)) 633 return 1; 634 635@@ -518,12 +534,15 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, 636 { 637 grub_err_t err; 638 639- node = grub_malloc (sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); 640+ if (grub_mul (dir->stsize, sizeof (dir->stack[0]), &sz) || 641+ grub_add (sz, sizeof (*node), &sz)) 642+ return 0; 643+ 644+ node = grub_malloc (sz); 645 if (!node) 646 return 0; 647 648- grub_memcpy (node, dir, 649- sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); 650+ grub_memcpy (node, dir, sz); 651 652 node->stsize--; 653 err = read_chunk (dir->data, &node->ino, sizeof (node->ino), 654@@ -557,6 +576,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, 655 enum grub_fshelp_filetype filetype = GRUB_FSHELP_REG; 656 struct grub_squash_dirent di; 657 struct grub_squash_inode ino; 658+ grub_size_t sz; 659 660 err = read_chunk (dir->data, &di, sizeof (di), 661 grub_le_to_cpu64 (dir->data->sb.diroffset) 662@@ -589,13 +609,16 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, 663 if (grub_le_to_cpu16 (di.type) == SQUASH_TYPE_SYMLINK) 664 filetype = GRUB_FSHELP_SYMLINK; 665 666- node = grub_malloc (sizeof (*node) 667- + (dir->stsize + 1) * sizeof (dir->stack[0])); 668+ if (grub_add (dir->stsize, 1, &sz) || 669+ grub_mul (sz, sizeof (dir->stack[0]), &sz) || 670+ grub_add (sz, sizeof (*node), &sz)) 671+ return 0; 672+ 673+ node = grub_malloc (sz); 674 if (! node) 675 return 0; 676 677- grub_memcpy (node, dir, 678- sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); 679+ grub_memcpy (node, dir, sz - sizeof(dir->stack[0])); 680 681 node->ino = ino; 682 node->stack[node->stsize].ino_chunk = grub_le_to_cpu32 (dh.ino_chunk); 683diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c 684index a83761674..21ac7f446 100644 685--- a/grub-core/fs/udf.c 686+++ b/grub-core/fs/udf.c 687@@ -28,6 +28,7 @@ 688 #include <grub/charset.h> 689 #include <grub/datetime.h> 690 #include <grub/udf.h> 691+#include <grub/safemath.h> 692 693 GRUB_MOD_LICENSE ("GPLv3+"); 694 695@@ -890,9 +891,19 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf) 696 utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2]; 697 } 698 if (!outbuf) 699- outbuf = grub_malloc (utf16len * GRUB_MAX_UTF8_PER_UTF16 + 1); 700+ { 701+ grub_size_t size; 702+ 703+ if (grub_mul (utf16len, GRUB_MAX_UTF8_PER_UTF16, &size) || 704+ grub_add (size, 1, &size)) 705+ goto fail; 706+ 707+ outbuf = grub_malloc (size); 708+ } 709 if (outbuf) 710 *grub_utf16_to_utf8 ((grub_uint8_t *) outbuf, utf16, utf16len) = '\0'; 711+ 712+ fail: 713 grub_free (utf16); 714 return outbuf; 715 } 716@@ -1005,7 +1016,7 @@ grub_udf_read_symlink (grub_fshelp_node_t node) 717 grub_size_t sz = U64 (node->block.fe.file_size); 718 grub_uint8_t *raw; 719 const grub_uint8_t *ptr; 720- char *out, *optr; 721+ char *out = NULL, *optr; 722 723 if (sz < 4) 724 return NULL; 725@@ -1013,14 +1024,16 @@ grub_udf_read_symlink (grub_fshelp_node_t node) 726 if (!raw) 727 return NULL; 728 if (grub_udf_read_file (node, NULL, NULL, 0, sz, (char *) raw) < 0) 729- { 730- grub_free (raw); 731- return NULL; 732- } 733+ goto fail_1; 734 735- out = grub_malloc (sz * 2 + 1); 736+ if (grub_mul (sz, 2, &sz) || 737+ grub_add (sz, 1, &sz)) 738+ goto fail_0; 739+ 740+ out = grub_malloc (sz); 741 if (!out) 742 { 743+ fail_0: 744 grub_free (raw); 745 return NULL; 746 } 747@@ -1031,17 +1044,17 @@ grub_udf_read_symlink (grub_fshelp_node_t node) 748 { 749 grub_size_t s; 750 if ((grub_size_t) (ptr - raw + 4) > sz) 751- goto fail; 752+ goto fail_1; 753 if (!(ptr[2] == 0 && ptr[3] == 0)) 754- goto fail; 755+ goto fail_1; 756 s = 4 + ptr[1]; 757 if ((grub_size_t) (ptr - raw + s) > sz) 758- goto fail; 759+ goto fail_1; 760 switch (*ptr) 761 { 762 case 1: 763 if (ptr[1]) 764- goto fail; 765+ goto fail_1; 766 /* Fallthrough. */ 767 case 2: 768 /* in 4 bytes. out: 1 byte. */ 769@@ -1066,11 +1079,11 @@ grub_udf_read_symlink (grub_fshelp_node_t node) 770 if (optr != out) 771 *optr++ = '/'; 772 if (!read_string (ptr + 4, s - 4, optr)) 773- goto fail; 774+ goto fail_1; 775 optr += grub_strlen (optr); 776 break; 777 default: 778- goto fail; 779+ goto fail_1; 780 } 781 ptr += s; 782 } 783@@ -1078,7 +1091,7 @@ grub_udf_read_symlink (grub_fshelp_node_t node) 784 grub_free (raw); 785 return out; 786 787- fail: 788+ fail_1: 789 grub_free (raw); 790 grub_free (out); 791 grub_error (GRUB_ERR_BAD_FS, "invalid symlink"); 792diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c 793index 96ffecbfc..ea6590290 100644 794--- a/grub-core/fs/xfs.c 795+++ b/grub-core/fs/xfs.c 796@@ -25,6 +25,7 @@ 797 #include <grub/dl.h> 798 #include <grub/types.h> 799 #include <grub/fshelp.h> 800+#include <grub/safemath.h> 801 802 GRUB_MOD_LICENSE ("GPLv3+"); 803 804@@ -899,6 +900,7 @@ static struct grub_xfs_data * 805 grub_xfs_mount (grub_disk_t disk) 806 { 807 struct grub_xfs_data *data = 0; 808+ grub_size_t sz; 809 810 data = grub_zalloc (sizeof (struct grub_xfs_data)); 811 if (!data) 812@@ -913,10 +915,11 @@ grub_xfs_mount (grub_disk_t disk) 813 if (!grub_xfs_sb_valid(data)) 814 goto fail; 815 816- data = grub_realloc (data, 817- sizeof (struct grub_xfs_data) 818- - sizeof (struct grub_xfs_inode) 819- + grub_xfs_inode_size(data) + 1); 820+ if (grub_add (grub_xfs_inode_size (data), 821+ sizeof (struct grub_xfs_data) - sizeof (struct grub_xfs_inode) + 1, &sz)) 822+ goto fail; 823+ 824+ data = grub_realloc (data, sz); 825 826 if (! data) 827 goto fail; 828diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c 829index 381dde556..36d0373a6 100644 830--- a/grub-core/fs/zfs/zfs.c 831+++ b/grub-core/fs/zfs/zfs.c 832@@ -55,6 +55,7 @@ 833 #include <grub/deflate.h> 834 #include <grub/crypto.h> 835 #include <grub/i18n.h> 836+#include <grub/safemath.h> 837 838 GRUB_MOD_LICENSE ("GPLv3+"); 839 840@@ -773,11 +774,14 @@ fill_vdev_info (struct grub_zfs_data *data, 841 if (data->n_devices_attached > data->n_devices_allocated) 842 { 843 void *tmp; 844- data->n_devices_allocated = 2 * data->n_devices_attached + 1; 845- data->devices_attached 846- = grub_realloc (tmp = data->devices_attached, 847- data->n_devices_allocated 848- * sizeof (data->devices_attached[0])); 849+ grub_size_t sz; 850+ 851+ if (grub_mul (data->n_devices_attached, 2, &data->n_devices_allocated) || 852+ grub_add (data->n_devices_allocated, 1, &data->n_devices_allocated) || 853+ grub_mul (data->n_devices_allocated, sizeof (data->devices_attached[0]), &sz)) 854+ return GRUB_ERR_OUT_OF_RANGE; 855+ 856+ data->devices_attached = grub_realloc (tmp = data->devices_attached, sz); 857 if (!data->devices_attached) 858 { 859 data->devices_attached = tmp; 860@@ -3468,14 +3472,18 @@ grub_zfs_nvlist_lookup_nvlist (const char *nvlist, const char *name) 861 { 862 char *nvpair; 863 char *ret; 864- grub_size_t size; 865+ grub_size_t size, sz; 866 int found; 867 868 found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST, &nvpair, 869 &size, 0); 870 if (!found) 871 return 0; 872- ret = grub_zalloc (size + 3 * sizeof (grub_uint32_t)); 873+ 874+ if (grub_add (size, 3 * sizeof (grub_uint32_t), &sz)) 875+ return 0; 876+ 877+ ret = grub_zalloc (sz); 878 if (!ret) 879 return 0; 880 grub_memcpy (ret, nvlist, sizeof (grub_uint32_t)); 881diff --git a/grub-core/fs/zfs/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c 882index 1402e0bc2..de3b015f5 100644 883--- a/grub-core/fs/zfs/zfscrypt.c 884+++ b/grub-core/fs/zfs/zfscrypt.c 885@@ -22,6 +22,7 @@ 886 #include <grub/misc.h> 887 #include <grub/disk.h> 888 #include <grub/partition.h> 889+#include <grub/safemath.h> 890 #include <grub/dl.h> 891 #include <grub/types.h> 892 #include <grub/zfs/zfs.h> 893@@ -82,9 +83,13 @@ grub_zfs_add_key (grub_uint8_t *key_in, 894 int passphrase) 895 { 896 struct grub_zfs_wrap_key *key; 897+ grub_size_t sz; 898+ 899 if (!passphrase && keylen > 32) 900 keylen = 32; 901- key = grub_malloc (sizeof (*key) + keylen); 902+ if (grub_add (sizeof (*key), keylen, &sz)) 903+ return GRUB_ERR_OUT_OF_RANGE; 904+ key = grub_malloc (sz); 905 if (!key) 906 return grub_errno; 907 key->is_passphrase = passphrase; 908diff --git a/grub-core/lib/arg.c b/grub-core/lib/arg.c 909index fd7744a6f..3288609a5 100644 910--- a/grub-core/lib/arg.c 911+++ b/grub-core/lib/arg.c 912@@ -23,6 +23,7 @@ 913 #include <grub/term.h> 914 #include <grub/extcmd.h> 915 #include <grub/i18n.h> 916+#include <grub/safemath.h> 917 918 /* Built-in parser for default options. */ 919 static const struct grub_arg_option help_options[] = 920@@ -216,7 +217,13 @@ static inline grub_err_t 921 add_arg (char ***argl, int *num, char *s) 922 { 923 char **p = *argl; 924- *argl = grub_realloc (*argl, (++(*num) + 1) * sizeof (char *)); 925+ grub_size_t sz; 926+ 927+ if (grub_add (++(*num), 1, &sz) || 928+ grub_mul (sz, sizeof (char *), &sz)) 929+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); 930+ 931+ *argl = grub_realloc (*argl, sz); 932 if (! *argl) 933 { 934 grub_free (p); 935@@ -431,6 +438,7 @@ grub_arg_list_alloc(grub_extcmd_t extcmd, int argc, 936 grub_size_t argcnt; 937 struct grub_arg_list *list; 938 const struct grub_arg_option *options; 939+ grub_size_t sz0, sz1; 940 941 options = extcmd->options; 942 if (! options) 943@@ -443,7 +451,15 @@ grub_arg_list_alloc(grub_extcmd_t extcmd, int argc, 944 argcnt += ((grub_size_t) argc + 1) / 2 + 1; /* max possible for any option */ 945 } 946 947- list = grub_zalloc (sizeof (*list) * i + sizeof (char*) * argcnt); 948+ if (grub_mul (sizeof (*list), i, &sz0) || 949+ grub_mul (sizeof (char *), argcnt, &sz1) || 950+ grub_add (sz0, sz1, &sz0)) 951+ { 952+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); 953+ return 0; 954+ } 955+ 956+ list = grub_zalloc (sz0); 957 if (! list) 958 return 0; 959 960diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c 961index 3730ed382..b92cbe98d 100644 962--- a/grub-core/loader/i386/bsd.c 963+++ b/grub-core/loader/i386/bsd.c 964@@ -35,6 +35,7 @@ 965 #include <grub/ns8250.h> 966 #include <grub/bsdlabel.h> 967 #include <grub/crypto.h> 968+#include <grub/safemath.h> 969 #include <grub/verify.h> 970 #ifdef GRUB_MACHINE_PCBIOS 971 #include <grub/machine/int.h> 972@@ -1012,11 +1013,16 @@ grub_netbsd_add_modules (void) 973 struct grub_netbsd_btinfo_modules *mods; 974 unsigned i; 975 grub_err_t err; 976+ grub_size_t sz; 977 978 for (mod = netbsd_mods; mod; mod = mod->next) 979 modcnt++; 980 981- mods = grub_malloc (sizeof (*mods) + sizeof (mods->mods[0]) * modcnt); 982+ if (grub_mul (modcnt, sizeof (mods->mods[0]), &sz) || 983+ grub_add (sz, sizeof (*mods), &sz)) 984+ return GRUB_ERR_OUT_OF_RANGE; 985+ 986+ mods = grub_malloc (sz); 987 if (!mods) 988 return grub_errno; 989 990diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c 991index e332d5eb4..906ec7d67 100644 992--- a/grub-core/net/dns.c 993+++ b/grub-core/net/dns.c 994@@ -22,6 +22,7 @@ 995 #include <grub/i18n.h> 996 #include <grub/err.h> 997 #include <grub/time.h> 998+#include <grub/safemath.h> 999 1000 struct dns_cache_element 1001 { 1002@@ -51,9 +52,15 @@ grub_net_add_dns_server (const struct grub_net_network_level_address *s) 1003 { 1004 int na = dns_servers_alloc * 2; 1005 struct grub_net_network_level_address *ns; 1006+ grub_size_t sz; 1007+ 1008 if (na < 8) 1009 na = 8; 1010- ns = grub_realloc (dns_servers, na * sizeof (ns[0])); 1011+ 1012+ if (grub_mul (na, sizeof (ns[0]), &sz)) 1013+ return GRUB_ERR_OUT_OF_RANGE; 1014+ 1015+ ns = grub_realloc (dns_servers, sz); 1016 if (!ns) 1017 return grub_errno; 1018 dns_servers_alloc = na; 1019diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c 1020index d57fb72fa..4dfcc3107 100644 1021--- a/grub-core/normal/charset.c 1022+++ b/grub-core/normal/charset.c 1023@@ -48,6 +48,7 @@ 1024 #include <grub/unicode.h> 1025 #include <grub/term.h> 1026 #include <grub/normal.h> 1027+#include <grub/safemath.h> 1028 1029 #if HAVE_FONT_SOURCE 1030 #include "widthspec.h" 1031@@ -464,6 +465,7 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen, 1032 { 1033 struct grub_unicode_combining *n; 1034 unsigned j; 1035+ grub_size_t sz; 1036 1037 if (!haveout) 1038 continue; 1039@@ -477,10 +479,14 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen, 1040 n = out->combining_inline; 1041 else if (out->ncomb > (int) ARRAY_SIZE (out->combining_inline)) 1042 { 1043- n = grub_realloc (out->combining_ptr, 1044- sizeof (n[0]) * (out->ncomb + 1)); 1045+ if (grub_add (out->ncomb, 1, &sz) || 1046+ grub_mul (sz, sizeof (n[0]), &sz)) 1047+ goto fail; 1048+ 1049+ n = grub_realloc (out->combining_ptr, sz); 1050 if (!n) 1051 { 1052+ fail: 1053 grub_errno = GRUB_ERR_NONE; 1054 continue; 1055 } 1056diff --git a/grub-core/normal/cmdline.c b/grub-core/normal/cmdline.c 1057index c57242e2e..de03fe63b 100644 1058--- a/grub-core/normal/cmdline.c 1059+++ b/grub-core/normal/cmdline.c 1060@@ -28,6 +28,7 @@ 1061 #include <grub/env.h> 1062 #include <grub/i18n.h> 1063 #include <grub/charset.h> 1064+#include <grub/safemath.h> 1065 1066 static grub_uint32_t *kill_buf; 1067 1068@@ -307,12 +308,21 @@ cl_insert (struct cmdline_term *cl_terms, unsigned nterms, 1069 if (len + (*llen) >= (*max_len)) 1070 { 1071 grub_uint32_t *nbuf; 1072- (*max_len) *= 2; 1073- nbuf = grub_realloc ((*buf), sizeof (grub_uint32_t) * (*max_len)); 1074+ grub_size_t sz; 1075+ 1076+ if (grub_mul (*max_len, 2, max_len) || 1077+ grub_mul (*max_len, sizeof (grub_uint32_t), &sz)) 1078+ { 1079+ grub_errno = GRUB_ERR_OUT_OF_RANGE; 1080+ goto fail; 1081+ } 1082+ 1083+ nbuf = grub_realloc ((*buf), sz); 1084 if (nbuf) 1085 (*buf) = nbuf; 1086 else 1087 { 1088+ fail: 1089 grub_print_error (); 1090 grub_errno = GRUB_ERR_NONE; 1091 (*max_len) /= 2; 1092diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c 1093index 1993995be..50eef918c 100644 1094--- a/grub-core/normal/menu_entry.c 1095+++ b/grub-core/normal/menu_entry.c 1096@@ -27,6 +27,7 @@ 1097 #include <grub/auth.h> 1098 #include <grub/i18n.h> 1099 #include <grub/charset.h> 1100+#include <grub/safemath.h> 1101 1102 enum update_mode 1103 { 1104@@ -113,10 +114,18 @@ ensure_space (struct line *linep, int extra) 1105 { 1106 if (linep->max_len < linep->len + extra) 1107 { 1108- linep->max_len = 2 * (linep->len + extra); 1109- linep->buf = grub_realloc (linep->buf, (linep->max_len + 1) * sizeof (linep->buf[0])); 1110+ grub_size_t sz0, sz1; 1111+ 1112+ if (grub_add (linep->len, extra, &sz0) || 1113+ grub_mul (sz0, 2, &sz0) || 1114+ grub_add (sz0, 1, &sz1) || 1115+ grub_mul (sz1, sizeof (linep->buf[0]), &sz1)) 1116+ return 0; 1117+ 1118+ linep->buf = grub_realloc (linep->buf, sz1); 1119 if (! linep->buf) 1120 return 0; 1121+ linep->max_len = sz0; 1122 } 1123 1124 return 1; 1125diff --git a/grub-core/script/argv.c b/grub-core/script/argv.c 1126index 217ec5d1e..5751fdd57 100644 1127--- a/grub-core/script/argv.c 1128+++ b/grub-core/script/argv.c 1129@@ -20,6 +20,7 @@ 1130 #include <grub/mm.h> 1131 #include <grub/misc.h> 1132 #include <grub/script_sh.h> 1133+#include <grub/safemath.h> 1134 1135 /* Return nearest power of two that is >= v. */ 1136 static unsigned 1137@@ -81,11 +82,16 @@ int 1138 grub_script_argv_next (struct grub_script_argv *argv) 1139 { 1140 char **p = argv->args; 1141+ grub_size_t sz; 1142 1143 if (argv->args && argv->argc && argv->args[argv->argc - 1] == 0) 1144 return 0; 1145 1146- p = grub_realloc (p, round_up_exp ((argv->argc + 2) * sizeof (char *))); 1147+ if (grub_add (argv->argc, 2, &sz) || 1148+ grub_mul (sz, sizeof (char *), &sz)) 1149+ return 1; 1150+ 1151+ p = grub_realloc (p, round_up_exp (sz)); 1152 if (! p) 1153 return 1; 1154 1155@@ -105,13 +111,19 @@ grub_script_argv_append (struct grub_script_argv *argv, const char *s, 1156 { 1157 grub_size_t a; 1158 char *p = argv->args[argv->argc - 1]; 1159+ grub_size_t sz; 1160 1161 if (! s) 1162 return 0; 1163 1164 a = p ? grub_strlen (p) : 0; 1165 1166- p = grub_realloc (p, round_up_exp ((a + slen + 1) * sizeof (char))); 1167+ if (grub_add (a, slen, &sz) || 1168+ grub_add (sz, 1, &sz) || 1169+ grub_mul (sz, sizeof (char), &sz)) 1170+ return 1; 1171+ 1172+ p = grub_realloc (p, round_up_exp (sz)); 1173 if (! p) 1174 return 1; 1175 1176diff --git a/grub-core/script/lexer.c b/grub-core/script/lexer.c 1177index c6bd3172f..5fb0cbd0b 100644 1178--- a/grub-core/script/lexer.c 1179+++ b/grub-core/script/lexer.c 1180@@ -24,6 +24,7 @@ 1181 #include <grub/mm.h> 1182 #include <grub/script_sh.h> 1183 #include <grub/i18n.h> 1184+#include <grub/safemath.h> 1185 1186 #define yytext_ptr char * 1187 #include "grub_script.tab.h" 1188@@ -110,10 +111,14 @@ grub_script_lexer_record (struct grub_parser_param *parser, char *str) 1189 old = lexer->recording; 1190 if (lexer->recordlen < len) 1191 lexer->recordlen = len; 1192- lexer->recordlen *= 2; 1193+ 1194+ if (grub_mul (lexer->recordlen, 2, &lexer->recordlen)) 1195+ goto fail; 1196+ 1197 lexer->recording = grub_realloc (lexer->recording, lexer->recordlen); 1198 if (!lexer->recording) 1199 { 1200+ fail: 1201 grub_free (old); 1202 lexer->recordpos = 0; 1203 lexer->recordlen = 0; 1204@@ -130,7 +135,7 @@ int 1205 grub_script_lexer_yywrap (struct grub_parser_param *parserstate, 1206 const char *input) 1207 { 1208- grub_size_t len = 0; 1209+ grub_size_t len = 0, sz; 1210 char *p = 0; 1211 char *line = 0; 1212 YY_BUFFER_STATE buffer; 1213@@ -168,12 +173,22 @@ grub_script_lexer_yywrap (struct grub_parser_param *parserstate, 1214 } 1215 else if (len && line[len - 1] != '\n') 1216 { 1217- p = grub_realloc (line, len + 2); 1218+ if (grub_add (len, 2, &sz)) 1219+ { 1220+ grub_free (line); 1221+ grub_script_yyerror (parserstate, N_("overflow is detected")); 1222+ return 1; 1223+ } 1224+ 1225+ p = grub_realloc (line, sz); 1226 if (p) 1227 { 1228 p[len++] = '\n'; 1229 p[len] = '\0'; 1230 } 1231+ else 1232+ grub_free (line); 1233+ 1234 line = p; 1235 } 1236 1237diff --git a/grub-core/video/bitmap.c b/grub-core/video/bitmap.c 1238index b2e031566..6256e209a 100644 1239--- a/grub-core/video/bitmap.c 1240+++ b/grub-core/video/bitmap.c 1241@@ -23,6 +23,7 @@ 1242 #include <grub/mm.h> 1243 #include <grub/misc.h> 1244 #include <grub/i18n.h> 1245+#include <grub/safemath.h> 1246 1247 GRUB_MOD_LICENSE ("GPLv3+"); 1248 1249@@ -58,7 +59,7 @@ grub_video_bitmap_create (struct grub_video_bitmap **bitmap, 1250 enum grub_video_blit_format blit_format) 1251 { 1252 struct grub_video_mode_info *mode_info; 1253- unsigned int size; 1254+ grub_size_t size; 1255 1256 if (!bitmap) 1257 return grub_error (GRUB_ERR_BUG, "invalid argument"); 1258@@ -137,19 +138,25 @@ grub_video_bitmap_create (struct grub_video_bitmap **bitmap, 1259 1260 mode_info->pitch = width * mode_info->bytes_per_pixel; 1261 1262- /* Calculate size needed for the data. */ 1263- size = (width * mode_info->bytes_per_pixel) * height; 1264+ /* Calculate size needed for the data. */ 1265+ if (grub_mul (width, mode_info->bytes_per_pixel, &size) || 1266+ grub_mul (size, height, &size)) 1267+ { 1268+ grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); 1269+ goto fail; 1270+ } 1271 1272 (*bitmap)->data = grub_zalloc (size); 1273 if (! (*bitmap)->data) 1274- { 1275- grub_free (*bitmap); 1276- *bitmap = 0; 1277- 1278- return grub_errno; 1279- } 1280+ goto fail; 1281 1282 return GRUB_ERR_NONE; 1283+ 1284+ fail: 1285+ grub_free (*bitmap); 1286+ *bitmap = NULL; 1287+ 1288+ return grub_errno; 1289 } 1290 1291 /* Frees all resources allocated by bitmap. */ 1292diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c 1293index 61bd64537..0157ff742 100644 1294--- a/grub-core/video/readers/png.c 1295+++ b/grub-core/video/readers/png.c 1296@@ -23,6 +23,7 @@ 1297 #include <grub/mm.h> 1298 #include <grub/misc.h> 1299 #include <grub/bufio.h> 1300+#include <grub/safemath.h> 1301 1302 GRUB_MOD_LICENSE ("GPLv3+"); 1303 1304@@ -301,9 +302,17 @@ grub_png_decode_image_header (struct grub_png_data *data) 1305 data->bpp <<= 1; 1306 1307 data->color_bits = color_bits; 1308- data->row_bytes = data->image_width * data->bpp; 1309+ 1310+ if (grub_mul (data->image_width, data->bpp, &data->row_bytes)) 1311+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); 1312+ 1313 if (data->color_bits <= 4) 1314- data->row_bytes = (data->image_width * data->color_bits + 7) / 8; 1315+ { 1316+ if (grub_mul (data->image_width, data->color_bits + 7, &data->row_bytes)) 1317+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); 1318+ 1319+ data->row_bytes >>= 3; 1320+ } 1321 1322 #ifndef GRUB_CPU_WORDS_BIGENDIAN 1323 if (data->is_16bit || data->is_gray || data->is_palette) 1324-- 13252.26.2 1326 1327