This patch cleans up some manual overflow checks to use stdckdint.h.

There are some others I noticed that could be cleaned up, but they
require some reorganization. So I will hold off on them.

Collin

>From 4eb83aaa4553a4d5f393eaf9db20697f81cbbb53 Mon Sep 17 00:00:00 2001
Message-ID: <4eb83aaa4553a4d5f393eaf9db20697f81cbbb53.1759009416.git.collin.fu...@gmail.com>
From: Collin Funk <[email protected]>
Date: Sat, 27 Sep 2025 14:34:44 -0700
Subject: [PATCH] maint: convert some overflow checks to ckd_add and ckd_mul

* src/csplit.c (parse_repeat_count): Prefer ckd_add when checking for
overflows.
* src/install.c (get_ids): Likewise.
* src/shred.c (dopass): Likewise.
* src/tr.c (get_spec_stats): Likewise.
* src/sort.c (specify_sort_size): Prefer ckd_mul when checking for
overflows.
---
 src/csplit.c  | 3 +--
 src/install.c | 6 ++----
 src/shred.c   | 4 +---
 src/sort.c    | 9 ++-------
 src/tr.c      | 5 +----
 5 files changed, 7 insertions(+), 20 deletions(-)

diff --git a/src/csplit.c b/src/csplit.c
index d2a928ae6..f3fccfcd5 100644
--- a/src/csplit.c
+++ b/src/csplit.c
@@ -1063,13 +1063,12 @@ parse_repeat_count (int argnum, struct control *p, char *str)
     {
       uintmax_t val;
       if (xstrtoumax (str + 1, nullptr, 10, &val, "") != LONGINT_OK
-          || INTMAX_MAX < val)
+          || ckd_add (&p->repeat, val, 0))
         {
           error (EXIT_FAILURE, 0,
                  _("%s}: integer required between '{' and '}'"),
                  quote (global_argv[argnum]));
         }
-      p->repeat = val;
     }
 
   *end = '}';
diff --git a/src/install.c b/src/install.c
index f8a814025..43c7729af 100644
--- a/src/install.c
+++ b/src/install.c
@@ -535,10 +535,9 @@ get_ids (void)
         {
           uintmax_t tmp;
           if (xstrtoumax (owner_name, nullptr, 0, &tmp, "") != LONGINT_OK
-              || UID_T_MAX < tmp)
+              || ckd_add (&owner_id, tmp, 0))
             error (EXIT_FAILURE, 0, _("invalid user %s"),
                    quoteaf (owner_name));
-          owner_id = tmp;
         }
       else
         owner_id = pw->pw_uid;
@@ -554,10 +553,9 @@ get_ids (void)
         {
           uintmax_t tmp;
           if (xstrtoumax (group_name, nullptr, 0, &tmp, "") != LONGINT_OK
-              || GID_T_MAX < tmp)
+              || ckd_add (&group_id, tmp, 0))
             error (EXIT_FAILURE, 0, _("invalid group %s"),
                    quoteaf (group_name));
-          group_id = tmp;
         }
       else
         group_id = gr->gr_gid;
diff --git a/src/shred.c b/src/shred.c
index cf782f16e..f2af24398 100644
--- a/src/shred.c
+++ b/src/shred.c
@@ -529,15 +529,13 @@ dopass (int fd, struct stat const *st, char const *qname, off_t *sizep,
 
       /* Okay, we have written "soff" bytes. */
 
-      if (OFF_T_MAX - offset < soff)
+      if (ckd_add (&offset, offset, soff))
         {
           error (0, 0, _("%s: file too large"), qname);
           other_error = true;
           goto free_pattern_mem;
         }
 
-      offset += soff;
-
       bool done = offset == size;
 
       /* Time to print progress? */
diff --git a/src/sort.c b/src/sort.c
index 0212695b1..077abf37b 100644
--- a/src/sort.c
+++ b/src/sort.c
@@ -1389,13 +1389,8 @@ specify_sort_size (int oi, char c, char const *s)
   enum strtol_error e = xstrtoumax (s, &suffix, 10, &n, "EgGkKmMPQRtTYZ");
 
   /* The default unit is KiB.  */
-  if (e == LONGINT_OK && c_isdigit (suffix[-1]))
-    {
-      if (n <= UINTMAX_MAX / 1024)
-        n *= 1024;
-      else
-        e = LONGINT_OVERFLOW;
-    }
+  if (e == LONGINT_OK && c_isdigit (suffix[-1]) && ckd_mul (&n, n, 1024))
+    e = LONGINT_OVERFLOW;
 
   /* A 'b' suffix means bytes; a '%' suffix means percent of memory.  */
   if (e == LONGINT_INVALID_SUFFIX_CHAR && c_isdigit (suffix[-1]) && ! suffix[1])
diff --git a/src/tr.c b/src/tr.c
index f172ced86..26776395f 100644
--- a/src/tr.c
+++ b/src/tr.c
@@ -1244,7 +1244,6 @@ get_spec_stats (struct Spec_list *s)
   for (p = s->head->next; p; p = p->next)
     {
       count len = 0;
-      count new_length;
 
       switch (p->type)
         {
@@ -1298,10 +1297,8 @@ get_spec_stats (struct Spec_list *s)
          any length greater than the maximum repeat count, in case the
          length is later used to compute the repeat count for an
          indefinite element.  */
-      new_length = length + len;
-      if (! (length <= new_length && new_length <= REPEAT_COUNT_MAXIMUM))
+      if (ckd_add (&length, length, len) || REPEAT_COUNT_MAXIMUM < length)
         error (EXIT_FAILURE, 0, _("too many characters in set"));
-      length = new_length;
     }
 
   s->length = length;
-- 
2.51.0

Reply via email to