diff options
author | Tobias Stoeckmann <tobias@stoeckmann.org> | 2023-12-14 12:33:35 +0100 |
---|---|---|
committer | Alejandro Colomar <alx@kernel.org> | 2024-02-14 04:07:55 +0100 |
commit | 541d4dde23e8cfaee8291d5a9289aa9de7fb80d2 (patch) | |
tree | ff50e07feb39dd38868611f9752f18298d3c18c9 | |
parent | 55f9635ecf1f637abb86f77ec456f7e69e9e9ebc (diff) |
src/chage.c: Unify long overflow checks in print_day_as_date()
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>
-rw-r--r-- | src/chage.c | 52 |
1 files changed, 27 insertions, 25 deletions
diff --git a/src/chage.c b/src/chage.c index 8a6d3584..ecbf8738 100644 --- a/src/chage.c +++ b/src/chage.c @@ -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 |