From f4787e73e7033b24d3270c3f1d89c41e15c6e88c Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Thu, 16 Nov 2023 16:36:03 +0100 Subject: lib/date_to_str.c, lib/prototypes.h, src/: Require a buffer size of >=64 for date_to_str() For common dates, 11 bytes should be enough: "YYYY-MM-DD" + NUL. But since the year comes from an int, one could make it need 20 bytes for some unrealistic year (in ILP64 architectures). Rounding up, that would give us 32 bytes for the buffer. Just to be a bit more cautious, make it 64. Now, we don't need to use strtcpy(), and can directly strcpy(3), since we have enough size for the strings we use: "never" and "future". Keep the error checking for strftime(3), just to be paranoid, but the expectation is that is should never fail. The compiler can enforce the limit, via -Wstringop-overflow=, which is enabled by -Wall. Signed-off-by: Alejandro Colomar --- lib/date_to_str.c | 11 +++++------ lib/prototypes.h | 2 +- src/chage.c | 4 ++-- src/passwd.c | 2 +- src/usermod.c | 7 ++++--- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/date_to_str.c b/lib/date_to_str.c index 4a5ca515..fade4b5a 100644 --- a/lib/date_to_str.c +++ b/lib/date_to_str.c @@ -11,30 +11,29 @@ #ident "$Id$" -#include "strtcpy.h" #include "prototypes.h" void -date_to_str(size_t size, char buf[size], long date) +date_to_str(char buf[64], long date) { time_t t; const struct tm *tm; t = date; if (date < 0) { - (void) strtcpy(buf, "never", size); + strcpy(buf, "never"); return; } tm = gmtime(&t); if (tm == NULL) { - (void) strtcpy(buf, "future", size); + strcpy(buf, "future"); return; } - if (strftime(buf, size, "%Y-%m-%d", tm) == 0) { - (void) strtcpy(buf, "future", size); + if (strftime(buf, 64, "%Y-%m-%d", tm) == 0) { + strcpy(buf, "future"); return; } } diff --git a/lib/prototypes.h b/lib/prototypes.h index 89a68e7c..5854b734 100644 --- a/lib/prototypes.h +++ b/lib/prototypes.h @@ -108,7 +108,7 @@ extern int copy_tree (const char *src_root, const char *dst_root, gid_t old_gid, gid_t new_gid); /* date_to_str.c */ -extern void date_to_str (size_t size, char buf[size], long date); +extern void date_to_str(char buf[64], long date); /* encrypt.c */ extern /*@exposed@*//*@null@*/char *pw_encrypt (const char *, const char *); diff --git a/src/chage.c b/src/chage.c index c3e457c9..54688b50 100644 --- a/src/chage.c +++ b/src/chage.c @@ -180,7 +180,7 @@ static int new_fields (void) if (-1 == lstchgdate || lstchgdate > LONG_MAX / SCALE) { strcpy (buf, "-1"); } else { - date_to_str (sizeof(buf), buf, lstchgdate * SCALE); + date_to_str(buf, lstchgdate * SCALE); } change_field (buf, sizeof buf, _("Last Password Change (YYYY-MM-DD)")); @@ -211,7 +211,7 @@ static int new_fields (void) if (-1 == expdate || LONG_MAX / SCALE < expdate) { strcpy (buf, "-1"); } else { - date_to_str (sizeof(buf), buf, expdate * SCALE); + date_to_str(buf, expdate * SCALE); } change_field (buf, sizeof buf, diff --git a/src/passwd.c b/src/passwd.c index 67608619..388ffeaf 100644 --- a/src/passwd.c +++ b/src/passwd.c @@ -454,7 +454,7 @@ static void print_status (const struct passwd *pw) sp = prefix_getspnam (pw->pw_name); /* local, no need for xprefix_getspnam */ if (NULL != sp) { - date_to_str (sizeof(date), date, sp->sp_lstchg * SCALE), + date_to_str(date, sp->sp_lstchg * SCALE), (void) printf ("%s %s %s %lld %lld %lld %lld\n", pw->pw_name, pw_status (sp->sp_pwdp), diff --git a/src/usermod.c b/src/usermod.c index 4f7c7f48..94395797 100644 --- a/src/usermod.c +++ b/src/usermod.c @@ -591,9 +591,10 @@ static void new_spent (struct spwd *spent) } if (eflg) { /* log dates rather than numbers of days. */ - char new_exp[16], old_exp[16]; - date_to_str (sizeof(new_exp), new_exp, user_newexpire * DAY); - date_to_str (sizeof(old_exp), old_exp, user_expire * DAY); + char new_exp[64], old_exp[64]; + + date_to_str(new_exp, user_newexpire * DAY); + date_to_str(old_exp, user_expire * DAY); #ifdef WITH_AUDIT audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "changing expiration date", -- cgit v1.2.3