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