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: 20100e4b22 ("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 674409e226 ("lib/: Saturate addition to avoid overflow")]
Signed-off-by: Alejandro Colomar <alx@kernel.org>
This commit is contained in:
Tobias Stoeckmann
2024-02-14 04:07:55 +01:00
committed by Alejandro Colomar
parent 55f9635ecf
commit 541d4dde23
+26 -24
View File
@@ -72,7 +72,7 @@ static long expdate;
/* local function prototypes */ /* local function prototypes */
NORETURN static void usage (int status); NORETURN static void usage (int status);
static int new_fields (void); 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 list_fields (void);
static void process_flags (int argc, char **argv); static void process_flags (int argc, char **argv);
static void check_flags (int argc, int opt_index); static void check_flags (int argc, int opt_index);
@@ -227,10 +227,22 @@ static int new_fields (void)
return 1; 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); tp = gmtime (&date);
if (NULL == tp) { if (NULL == tp) {
@@ -241,6 +253,7 @@ static void print_date (time_t date)
} }
} }
/* /*
* list_fields - display the current values of the expiration fields * 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) static void list_fields (void)
{ {
long changed = 0;
long expires;
/* /*
* The "last change" date is either "never" or the date the password * 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. * 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); (void) fputs (_("Last password change\t\t\t\t\t: "), stdout);
if (lstchgdate < 0 || lstchgdate > LONG_MAX / DAY) { if (lstchgdate == 0) {
(void) puts (_("never"));
} else if (lstchgdate == 0) {
(void) puts (_("password must be changed")); (void) puts (_("password must be changed"));
} else { } else {
changed = lstchgdate * DAY; print_day_as_date(lstchgdate);
print_date (changed);
} }
/* /*
@@ -277,11 +284,11 @@ static void list_fields (void)
} else if ( (lstchgdate < 0) } else if ( (lstchgdate < 0)
|| (maxdays >= 10000) || (maxdays >= 10000)
|| (maxdays < 0) || (maxdays < 0)
|| ((LONG_MAX - changed) / DAY < maxdays)) { || (LONG_MAX - lstchgdate < maxdays))
{
(void) puts (_("never")); (void) puts (_("never"));
} else { } else {
expires = changed + maxdays * DAY; print_day_as_date(lstchgdate + maxdays);
print_date (expires);
} }
/* /*
@@ -297,12 +304,12 @@ static void list_fields (void)
|| (inactdays < 0) || (inactdays < 0)
|| (maxdays >= 10000) || (maxdays >= 10000)
|| (maxdays < 0) || (maxdays < 0)
|| (maxdays > LONG_MAX - inactdays) || (LONG_MAX - inactdays < maxdays)
|| ((LONG_MAX - changed) / DAY < maxdays + inactdays)) { || (LONG_MAX - lstchgdate < maxdays + inactdays))
{
(void) puts (_("never")); (void) puts (_("never"));
} else { } else {
expires = changed + (maxdays + inactdays) * DAY; print_day_as_date(lstchgdate + maxdays + inactdays);
print_date (expires);
} }
/* /*
@@ -310,12 +317,7 @@ static void list_fields (void)
* password expiring or not. * password expiring or not.
*/ */
(void) fputs (_("Account expires\t\t\t\t\t\t: "), stdout); (void) fputs (_("Account expires\t\t\t\t\t\t: "), stdout);
if (expdate < 0 || LONG_MAX / DAY < expdate) { print_day_as_date(expdate);
(void) puts (_("never"));
} else {
expires = expdate * DAY;
print_date (expires);
}
/* /*
* Start with the easy numbers - the number of days before the * Start with the easy numbers - the number of days before the