]> code.ossystems Code Review - openembedded-core.git/blob
896a2145d4460a4c93c97da37a511657c4952423
[openembedded-core.git] /
1 From eb77d1ef65e25746acff43545f62a71360b15eec Mon Sep 17 00:00:00 2001
2 From: Peter Jones <pjones@redhat.com>
3 Date: Mon, 15 Jun 2020 12:28:27 -0400
4 Subject: [PATCH 6/9] malloc: Use overflow checking primitives where we do
5  complex allocations
6
7 This attempts to fix the places where we do the following where
8 arithmetic_expr may include unvalidated data:
9
10   X = grub_malloc(arithmetic_expr);
11
12 It accomplishes this by doing the arithmetic ahead of time using grub_add(),
13 grub_sub(), grub_mul() and testing for overflow before proceeding.
14
15 Among 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
27 Fixes: CVE-2020-14309, CVE-2020-14310, CVE-2020-14311
28
29 Signed-off-by: Peter Jones <pjones@redhat.com>
30 Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
31
32 Upstream-Status: Backport
33 CVE: CVE-2020-14309, CVE-2020-14310, CVE-2020-14311
34
35 Reference to upstream patch:
36 https://git.savannah.gnu.org/cgit/grub.git/commit/?id=3f05d693d1274965ffbe4ba99080dc2c570944c6
37
38 Signed-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
65 diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c
66 index 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;
128 diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c
129 index 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      }
230 diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c
231 index 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;
301 diff --git a/grub-core/font/font.c b/grub-core/font/font.c
302 index 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  
328 diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
329 index 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      }
385 diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
386 index 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  
420 diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c
421 index 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);
524 diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c
525 index 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,
588 diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c
589 index 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);
687 diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c
688 index 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");
796 diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c
797 index 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;
832 diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c
833 index 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));
885 diff --git a/grub-core/fs/zfs/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c
886 index 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;
912 diff --git a/grub-core/lib/arg.c b/grub-core/lib/arg.c
913 index 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  
964 diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c
965 index 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  
994 diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
995 index 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;
1023 diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c
1024 index 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                 }
1060 diff --git a/grub-core/normal/cmdline.c b/grub-core/normal/cmdline.c
1061 index 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;
1096 diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c
1097 index 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;
1129 diff --git a/grub-core/script/argv.c b/grub-core/script/argv.c
1130 index 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  
1180 diff --git a/grub-core/script/lexer.c b/grub-core/script/lexer.c
1181 index 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  
1241 diff --git a/grub-core/video/bitmap.c b/grub-core/video/bitmap.c
1242 index 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.  */
1296 diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
1297 index 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 -- 
1329 2.14.4
1330