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