summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Meyering <meyering@redhat.com>2012-07-15 18:18:03 +0200
committerJim Meyering <meyering@redhat.com>2012-07-15 19:11:45 +0200
commitac00d23e1a90dc5a8cd0f6de0e61eb401d5089d5 (patch)
treee94876b4676c65ad8b8fa84d9f5d7320944ba5df
parente380221333f4efd8d49b29b2690375c36eb90505 (diff)
downloadcoreutils-ac00d23e1a90dc5a8cd0f6de0e61eb401d5089d5.tar.xz
pinky,who: fix bug in latest change
* src/system.h (stzncpy): New function. * src/pinky.c (print_entry): Use stzncpy, not stpncpy. The latter does not NUL-terminate. I assumed that strncpy was the only function with such a horrible API. Today I learned that stpncpy also may not NUL-terminate its result. The bugs were introduced in commit v8.17-48-gf79263d. * src/who.c (print_user): Likewise. Thanks to Erik Auerswald for spotting my error.
-rw-r--r--src/pinky.c6
-rw-r--r--src/system.h14
-rw-r--r--src/who.c4
3 files changed, 19 insertions, 5 deletions
diff --git a/src/pinky.c b/src/pinky.c
index c01b12427..385949aa8 100644
--- a/src/pinky.c
+++ b/src/pinky.c
@@ -215,7 +215,7 @@ print_entry (const STRUCT_UTMP *utmp_ent)
absolute file name in ut_line. */
if ( ! IS_ABSOLUTE_FILE_NAME (utmp_ent->ut_line))
p = stpcpy (p, DEV_DIR_WITH_TRAILING_SLASH);
- stpncpy (p, utmp_ent->ut_line, sizeof (utmp_ent->ut_line));
+ stzncpy (p, utmp_ent->ut_line, sizeof (utmp_ent->ut_line));
if (stat (line, &stats) == 0)
{
@@ -235,7 +235,7 @@ print_entry (const STRUCT_UTMP *utmp_ent)
struct passwd *pw;
char name[UT_USER_SIZE + 1];
- stpncpy (name, UT_USER (utmp_ent), UT_USER_SIZE);
+ stzncpy (name, UT_USER (utmp_ent), UT_USER_SIZE);
pw = getpwnam (name);
if (pw == NULL)
/* TRANSLATORS: Real name is unknown; at most 19 characters. */
@@ -276,7 +276,7 @@ print_entry (const STRUCT_UTMP *utmp_ent)
char *display = NULL;
/* Copy the host name into UT_HOST, and ensure it's nul terminated. */
- stpncpy (ut_host, utmp_ent->ut_host, sizeof (utmp_ent->ut_host));
+ stzncpy (ut_host, utmp_ent->ut_host, sizeof (utmp_ent->ut_host));
/* Look for an X display. */
display = strchr (ut_host, ':');
diff --git a/src/system.h b/src/system.h
index 5e3b3cbde..6907603e6 100644
--- a/src/system.h
+++ b/src/system.h
@@ -626,6 +626,20 @@ The following directory is part of the cycle:\n %s\n"), \
} \
while (0)
+/* Like stpncpy, but do ensure that the result is NUL-terminated,
+ and do not NUL-pad out to LEN. I.e., when strnlen (src, len) == len,
+ this function writes a NUL byte into dest[len]. Thus, the destination
+ buffer must be at least LEN+1 bytes long. */
+static inline char *
+stzncpy (char *dest, char const *src, size_t len)
+{
+ char const *src_end = src + len;
+ while (src < src_end && *src)
+ *dest++ = *src++;
+ *dest = 0;
+ return dest;
+}
+
#ifndef ARRAY_CARDINALITY
# define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array))
#endif
diff --git a/src/who.c b/src/who.c
index 3ad800429..00a6e37de 100644
--- a/src/who.c
+++ b/src/who.c
@@ -350,7 +350,7 @@ print_user (const STRUCT_UTMP *utmp_ent, time_t boottime)
absolute file name in ut_line. */
if ( ! IS_ABSOLUTE_FILE_NAME (utmp_ent->ut_line))
p = stpcpy (p, DEV_DIR_WITH_TRAILING_SLASH);
- stpncpy (p, utmp_ent->ut_line, sizeof (utmp_ent->ut_line));
+ stzncpy (p, utmp_ent->ut_line, sizeof (utmp_ent->ut_line));
if (stat (line, &stats) == 0)
{
@@ -376,7 +376,7 @@ print_user (const STRUCT_UTMP *utmp_ent, time_t boottime)
char *display = NULL;
/* Copy the host name into UT_HOST, and ensure it's nul terminated. */
- stpncpy (ut_host, utmp_ent->ut_host, sizeof (utmp_ent->ut_host));
+ stzncpy (ut_host, utmp_ent->ut_host, sizeof (utmp_ent->ut_host));
/* Look for an X display. */
display = strchr (ut_host, ':');