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