0006-malloc-Use-overflow-checking-primitives-where-we-do-.patch 37 KB

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