]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
src/chage.c: Unify long overflow checks in print_day_as_date()
authorTobias Stoeckmann <tobias@stoeckmann.org>
Thu, 14 Dec 2023 11:33:35 +0000 (12:33 +0100)
committerAlejandro Colomar <alx@kernel.org>
Wed, 14 Feb 2024 03:07:55 +0000 (04:07 +0100)
The conversion from day to seconds can be done in print_date
(renamed to print_day_as_date for clarification).  This has the nice
benefit that DAY multiplication and long to time_t conversion are done
at just one place.

Co-developed-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Co-developed-by: Alejandro Colomar <alx@kernel.org>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Cherry-picked-from: 20100e4b22c3 ("src/chage.c: Unify long overflow checks in print_day_as_date()")
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Link: <https://github.com/shadow-maint/shadow/pull/876>
[alx: This is a pre-requisite for 674409e2265e ("lib/: Saturate addition to avoid overflow")]
Signed-off-by: Alejandro Colomar <alx@kernel.org>
src/chage.c

index 8a6d3584a8c8771e28043b87cf7a8c5c4e4b9657..ecbf8738a2e15674e1422f051eeb7555ad888160 100644 (file)
@@ -72,7 +72,7 @@ static long expdate;
 /* local function prototypes */
 NORETURN static void usage (int status);
 static int new_fields (void);
-static void print_date (time_t date);
+static void print_day_as_date (long day);
 static void list_fields (void);
 static void process_flags (int argc, char **argv);
 static void check_flags (int argc, int opt_index);
@@ -227,10 +227,22 @@ static int new_fields (void)
        return 1;
 }
 
-static void print_date (time_t date)
+
+static void
+print_day_as_date(long day)
 {
-       struct tm *tp;
-       char buf[80];
+       char       buf[80];
+       time_t     date;
+       struct tm  *tp;
+
+       if (day < 0) {
+               puts(_("never"));
+               return;
+       }
+       if (__builtin_mul_overflow(day, DAY, &date)) {
+               puts(_("future"));
+               return;
+       }
 
        tp = gmtime (&date);
        if (NULL == tp) {
@@ -241,6 +253,7 @@ static void print_date (time_t date)
        }
 }
 
+
 /*
  * list_fields - display the current values of the expiration fields
  *
@@ -250,21 +263,15 @@ static void print_date (time_t date)
  */
 static void list_fields (void)
 {
-       long changed = 0;
-       long expires;
-
        /*
         * The "last change" date is either "never" or the date the password
         * was last modified. The date is the number of days since 1/1/1970.
         */
        (void) fputs (_("Last password change\t\t\t\t\t: "), stdout);
-       if (lstchgdate < 0 || lstchgdate > LONG_MAX / DAY) {
-               (void) puts (_("never"));
-       } else if (lstchgdate == 0) {
+       if (lstchgdate == 0) {
                (void) puts (_("password must be changed"));
        } else {
-               changed = lstchgdate * DAY;
-               print_date (changed);
+               print_day_as_date(lstchgdate);
        }
 
        /*
@@ -277,11 +284,11 @@ static void list_fields (void)
        } else if (   (lstchgdate < 0)
                   || (maxdays >= 10000)
                   || (maxdays < 0)
-                  || ((LONG_MAX - changed) / DAY < maxdays)) {
+                  || (LONG_MAX - lstchgdate < maxdays))
+       {
                (void) puts (_("never"));
        } else {
-               expires = changed + maxdays * DAY;
-               print_date (expires);
+               print_day_as_date(lstchgdate + maxdays);
        }
 
        /*
@@ -297,12 +304,12 @@ static void list_fields (void)
                   || (inactdays < 0)
                   || (maxdays >= 10000)
                   || (maxdays < 0)
-                  || (maxdays > LONG_MAX - inactdays)
-                  || ((LONG_MAX - changed) / DAY < maxdays + inactdays)) {
+                  || (LONG_MAX - inactdays < maxdays)
+                  || (LONG_MAX - lstchgdate < maxdays + inactdays))
+       {
                (void) puts (_("never"));
        } else {
-               expires = changed + (maxdays + inactdays) * DAY;
-               print_date (expires);
+               print_day_as_date(lstchgdate + maxdays + inactdays);
        }
 
        /*
@@ -310,12 +317,7 @@ static void list_fields (void)
         * password expiring or not.
         */
        (void) fputs (_("Account expires\t\t\t\t\t\t: "), stdout);
-       if (expdate < 0 || LONG_MAX / DAY < expdate) {
-               (void) puts (_("never"));
-       } else {
-               expires = expdate * DAY;
-               print_date (expires);
-       }
+       print_day_as_date(expdate);
 
        /*
         * Start with the easy numbers - the number of days before the