diffutils-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 16/17] maint: refactor integer overflow checking


From: Paul Eggert
Subject: [PATCH 16/17] maint: refactor integer overflow checking
Date: Sun, 22 Aug 2021 14:03:05 -0700

Rely on more-modern Gnulib capabilities instead of doing
integer overflow checking by hand, in some cases.
* lib/cmpbuf.c (buffer_lcm):
* src/io.c (slurp, find_identical_ends):
Use INT_ADD_WRAPV and INT_MULTIPLY_WRAPV rather than checking
overflow by hand.
* src/diff3.c (process_diff):
* src/dir.c (dir_read):
* src/io.c (find_identical_ends, read_files):
Use xnmalloc rather than checking overflow by hand.
(read_files): Rely on xcalloc to do overflow checking.
---
 lib/cmpbuf.c |  3 +--
 src/diff3.c  | 15 ++++-----------
 src/dir.c    |  4 +---
 src/io.c     | 21 ++++++++-------------
 4 files changed, 14 insertions(+), 29 deletions(-)

diff --git a/lib/cmpbuf.c b/lib/cmpbuf.c
index 7cee45a..f7c34e2 100644
--- a/lib/cmpbuf.c
+++ b/lib/cmpbuf.c
@@ -104,6 +104,5 @@ buffer_lcm (size_t a, size_t b, size_t lcm_max)
 
   /* Yield a if there is an overflow.  */
   q = a / n;
-  lcm = q * b;
-  return lcm <= lcm_max && lcm / b == q ? lcm : a;
+  return !INT_MULTIPLY_WRAPV (q, b, &lcm) && lcm <= lcm_max ? lcm : a;
 }
diff --git a/src/diff3.c b/src/diff3.c
index c67eb40..9e4ad54 100644
--- a/src/diff3.c
+++ b/src/diff3.c
@@ -1008,9 +1008,6 @@ process_diff (char const *filea,
   lin i;
   struct diff_block *block_list;
   struct diff_block **block_list_end = &block_list;
-  size_t too_many_lines = (PTRDIFF_MAX
-                           / MIN (sizeof *block_list->lines[1],
-                                  sizeof *block_list->lengths[1]));
 
   diff_limit = read_diff (filea, fileb, &diff_contents);
   *buf_to_free = diff_contents;
@@ -1056,10 +1053,8 @@ process_diff (char const *filea,
       if (dt != ADD)
         {
           lin numlines = D_NUMLINES (bptr, 0);
-          if (too_many_lines <= numlines)
-            xalloc_die ();
-          bptr->lines[0] = xmalloc (numlines * sizeof *bptr->lines[0]);
-          bptr->lengths[0] = xmalloc (numlines * sizeof *bptr->lengths[0]);
+          bptr->lines[0] = xnmalloc (numlines, sizeof *bptr->lines[0]);
+          bptr->lengths[0] = xnmalloc (numlines, sizeof *bptr->lengths[0]);
           for (i = 0; i < numlines; i++)
             scan_diff = scan_diff_line (scan_diff,
                                         &(bptr->lines[0][i]),
@@ -1081,10 +1076,8 @@ process_diff (char const *filea,
       if (dt != DELETE)
         {
           lin numlines = D_NUMLINES (bptr, 1);
-          if (too_many_lines <= numlines)
-            xalloc_die ();
-          bptr->lines[1] = xmalloc (numlines * sizeof *bptr->lines[1]);
-          bptr->lengths[1] = xmalloc (numlines * sizeof *bptr->lengths[1]);
+          bptr->lines[1] = xnmalloc (numlines, sizeof *bptr->lines[1]);
+          bptr->lengths[1] = xnmalloc (numlines, sizeof *bptr->lengths[1]);
           for (i = 0; i < numlines; i++)
             scan_diff = scan_diff_line (scan_diff,
                                         &(bptr->lines[1][i]),
diff --git a/src/dir.c b/src/dir.c
index 3ffb953..409eee4 100644
--- a/src/dir.c
+++ b/src/dir.c
@@ -126,9 +126,7 @@ dir_read (struct file_data const *dir, struct dirdata 
*dirdata)
     }
 
   /* Create the 'names' table from the 'data' table.  */
-  if (PTRDIFF_MAX / sizeof *names - 1 <= nnames)
-    xalloc_die ();
-  dirdata->names = names = xmalloc ((nnames + 1) * sizeof *names);
+  dirdata->names = names = xnmalloc (nnames + 1, sizeof *names);
   dirdata->nnames = nnames;
   for (i = 0;  i < nnames;  i++)
     {
diff --git a/src/io.c b/src/io.c
index 77fc070..f964caf 100644
--- a/src/io.c
+++ b/src/io.c
@@ -165,10 +165,9 @@ slurp (struct file_data *current)
       /* Get the size out of the stat block.
          Allocate just enough room for appended newline plus word sentinel,
          plus word-alignment since we want the buffer word-aligned.  */
-      size_t file_size = current->stat.st_size;
-      cc = file_size + 2 * sizeof (word) - file_size % sizeof (word);
-      if (file_size != current->stat.st_size || cc < file_size
-          || PTRDIFF_MAX <= cc)
+      off_t file_size = current->stat.st_size;
+      if (INT_ADD_WRAPV (2 * sizeof (word) - file_size % sizeof (word),
+                        file_size, &cc))
         xalloc_die ();
 
       if (current->bufsize < cc)
@@ -716,11 +715,11 @@ find_identical_ends (struct file_data filevec[])
 
   middle_guess = guess_lines (lines, p0 - buffer0, p1 - filevec[1].prefix_end);
   suffix_guess = guess_lines (lines, p0 - buffer0, buffer1 + n1 - p1);
-  alloc_lines1 = buffered_prefix + middle_guess + MIN (context, suffix_guess);
-  if (alloc_lines1 < buffered_prefix
-      || PTRDIFF_MAX / sizeof *linbuf1 <= alloc_lines1)
+  if (INT_ADD_WRAPV (buffered_prefix,
+                    middle_guess + MIN (context, suffix_guess),
+                    &alloc_lines1))
     xalloc_die ();
-  linbuf1 = xmalloc (alloc_lines1 * sizeof *linbuf1);
+  linbuf1 = xnmalloc (alloc_lines1, sizeof *linbuf1);
 
   if (buffered_prefix != lines)
     {
@@ -791,9 +790,7 @@ read_files (struct file_data filevec[], bool pretend_binary)
   find_identical_ends (filevec);
 
   equivs_alloc = filevec[0].alloc_lines + filevec[1].alloc_lines + 1;
-  if (PTRDIFF_MAX / sizeof *equivs <= equivs_alloc)
-    xalloc_die ();
-  equivs = xmalloc (equivs_alloc * sizeof *equivs);
+  equivs = xnmalloc (equivs_alloc, sizeof *equivs);
   /* Equivalence class 0 is permanently safe for lines that were not
      hashed.  Real equivalence classes start at 1.  */
   equivs_index = 1;
@@ -804,8 +801,6 @@ read_files (struct file_data filevec[], bool pretend_binary)
   for (i = 9; (size_t) 1 << i < equivs_alloc / 3; i++)
     continue;
   nbuckets = ((size_t) 1 << i) - prime_offset[i];
-  if (PTRDIFF_MAX / sizeof *buckets <= nbuckets)
-    xalloc_die ();
   buckets = xcalloc (nbuckets + 1, sizeof *buckets);
   buckets++;
 
-- 
2.31.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]