1
0
mirror of git://git.sv.gnu.org/coreutils.git synced 2026-04-15 00:12:00 +02:00

Add a little infrastructure to help prevent future bugs like the

one fixed today.

(xstrcat): New function.
(print_statfs, print_stat): Add buf_len parameter and convert all
uses of strcat to xstrcat.  Update callers.
(print_it): Call print_func with buf_len parameter.
This commit is contained in:
Jim Meyering
2005-03-12 10:59:23 +00:00
parent d9d9836223
commit e1ba36b607

View File

@@ -295,9 +295,22 @@ human_time (time_t t, int t_ns)
return str;
}
/* Like strcat, but don't return anything and do check that
DEST_BUFSIZE is at least a long as strlen (DEST) + strlen (SRC) + 1.
The signature is deliberately different from that of strncat. */
static void
xstrcat (char *dest, size_t dest_bufsize, char const *src)
{
size_t dest_len = strlen (dest);
size_t src_len = strlen (src);
if (dest_bufsize < dest_len + src_len + 1)
abort ();
memcpy (dest + dest_len, src, src_len + 1);
}
/* print statfs info */
static void
print_statfs (char *pformat, char m, char const *filename,
print_statfs (char *pformat, size_t buf_len, char m, char const *filename,
void const *data)
{
STRUCT_STATVFS const *statfsbuf = data;
@@ -305,28 +318,28 @@ print_statfs (char *pformat, char m, char const *filename,
switch (m)
{
case 'n':
strcat (pformat, "s");
xstrcat (pformat, buf_len, "s");
printf (pformat, filename);
break;
case 'i':
#if HAVE_STRUCT_STATXFS_F_FSID___VAL
strcat (pformat, "x %-8x");
xstrcat (pformat, buf_len, "x %-8x");
printf (pformat, statfsbuf->f_fsid.__val[0], /* u_long */
statfsbuf->f_fsid.__val[1]);
#else
strcat (pformat, "Lx");
xstrcat (pformat, buf_len, "Lx");
printf (pformat, statfsbuf->f_fsid);
#endif
break;
case 'l':
strcat (pformat, NAMEMAX_FORMAT);
xstrcat (pformat, buf_len, NAMEMAX_FORMAT);
printf (pformat, SB_F_NAMEMAX (statfsbuf));
break;
case 't':
#if HAVE_STRUCT_STATXFS_F_TYPE
strcat (pformat, "lx");
xstrcat (pformat, buf_len, "lx");
printf (pformat,
(unsigned long int) (statfsbuf->f_type)); /* no equiv. */
#else
@@ -334,23 +347,23 @@ print_statfs (char *pformat, char m, char const *filename,
#endif
break;
case 'T':
strcat (pformat, "s");
xstrcat (pformat, buf_len, "s");
printf (pformat, human_fstype (statfsbuf));
break;
case 'b':
strcat (pformat, PRIdMAX);
xstrcat (pformat, buf_len, PRIdMAX);
printf (pformat, (intmax_t) (statfsbuf->f_blocks));
break;
case 'f':
strcat (pformat, PRIdMAX);
xstrcat (pformat, buf_len, PRIdMAX);
printf (pformat, (intmax_t) (statfsbuf->f_bfree));
break;
case 'a':
strcat (pformat, PRIdMAX);
xstrcat (pformat, buf_len, PRIdMAX);
printf (pformat, (intmax_t) (statfsbuf->f_bavail));
break;
case 's':
strcat (pformat, "lu");
xstrcat (pformat, buf_len, "lu");
printf (pformat, (unsigned long int) (statfsbuf->f_bsize));
break;
case 'S':
@@ -358,21 +371,21 @@ print_statfs (char *pformat, char m, char const *filename,
unsigned long int frsize = STATFS_FRSIZE (statfsbuf);
if (! frsize)
frsize = statfsbuf->f_bsize;
strcat (pformat, "lu");
xstrcat (pformat, buf_len, "lu");
printf (pformat, frsize);
}
break;
case 'c':
strcat (pformat, PRIdMAX);
xstrcat (pformat, buf_len, PRIdMAX);
printf (pformat, (intmax_t) (statfsbuf->f_files));
break;
case 'd':
strcat (pformat, PRIdMAX);
xstrcat (pformat, buf_len, PRIdMAX);
printf (pformat, (intmax_t) (statfsbuf->f_ffree));
break;
default:
strcat (pformat, "c");
xstrcat (pformat, buf_len, "c");
printf (pformat, m);
break;
}
@@ -380,7 +393,8 @@ print_statfs (char *pformat, char m, char const *filename,
/* print stat info */
static void
print_stat (char *pformat, char m, char const *filename, void const *data)
print_stat (char *pformat, size_t buf_len, char m,
char const *filename, void const *data)
{
struct stat *statbuf = (struct stat *) data;
struct passwd *pw_ent;
@@ -389,11 +403,11 @@ print_stat (char *pformat, char m, char const *filename, void const *data)
switch (m)
{
case 'n':
strcat (pformat, "s");
xstrcat (pformat, buf_len, "s");
printf (pformat, filename);
break;
case 'N':
strcat (pformat, "s");
xstrcat (pformat, buf_len, "s");
if (S_ISLNK (statbuf->st_mode))
{
char *linkname = xreadlink (filename, statbuf->st_size);
@@ -414,111 +428,111 @@ print_stat (char *pformat, char m, char const *filename, void const *data)
}
break;
case 'd':
strcat (pformat, PRIuMAX);
xstrcat (pformat, buf_len, PRIuMAX);
printf (pformat, (uintmax_t) statbuf->st_dev);
break;
case 'D':
strcat (pformat, PRIxMAX);
xstrcat (pformat, buf_len, PRIxMAX);
printf (pformat, (uintmax_t) statbuf->st_dev);
break;
case 'i':
strcat (pformat, PRIuMAX);
xstrcat (pformat, buf_len, PRIuMAX);
printf (pformat, (uintmax_t) statbuf->st_ino);
break;
case 'a':
strcat (pformat, "lo");
xstrcat (pformat, buf_len, "lo");
printf (pformat,
(unsigned long int) (statbuf->st_mode & CHMOD_MODE_BITS));
break;
case 'A':
strcat (pformat, "s");
xstrcat (pformat, buf_len, "s");
printf (pformat, human_access (statbuf));
break;
case 'f':
strcat (pformat, "lx");
xstrcat (pformat, buf_len, "lx");
printf (pformat, (unsigned long int) statbuf->st_mode);
break;
case 'F':
strcat (pformat, "s");
xstrcat (pformat, buf_len, "s");
printf (pformat, file_type (statbuf));
break;
case 'h':
strcat (pformat, "lu");
xstrcat (pformat, buf_len, "lu");
printf (pformat, (unsigned long int) statbuf->st_nlink);
break;
case 'u':
strcat (pformat, "lu");
xstrcat (pformat, buf_len, "lu");
printf (pformat, (unsigned long int) statbuf->st_uid);
break;
case 'U':
strcat (pformat, "s");
xstrcat (pformat, buf_len, "s");
setpwent ();
pw_ent = getpwuid (statbuf->st_uid);
printf (pformat, (pw_ent != 0L) ? pw_ent->pw_name : "UNKNOWN");
break;
case 'g':
strcat (pformat, "lu");
xstrcat (pformat, buf_len, "lu");
printf (pformat, (unsigned long int) statbuf->st_gid);
break;
case 'G':
strcat (pformat, "s");
xstrcat (pformat, buf_len, "s");
setgrent ();
gw_ent = getgrgid (statbuf->st_gid);
printf (pformat, (gw_ent != 0L) ? gw_ent->gr_name : "UNKNOWN");
break;
case 't':
strcat (pformat, "lx");
xstrcat (pformat, buf_len, "lx");
printf (pformat, (unsigned long int) major (statbuf->st_rdev));
break;
case 'T':
strcat (pformat, "lx");
xstrcat (pformat, buf_len, "lx");
printf (pformat, (unsigned long int) minor (statbuf->st_rdev));
break;
case 's':
strcat (pformat, PRIuMAX);
xstrcat (pformat, buf_len, PRIuMAX);
printf (pformat, (uintmax_t) (statbuf->st_size));
break;
case 'B':
strcat (pformat, "lu");
xstrcat (pformat, buf_len, "lu");
printf (pformat, (unsigned long int) ST_NBLOCKSIZE);
break;
case 'b':
strcat (pformat, PRIuMAX);
xstrcat (pformat, buf_len, PRIuMAX);
printf (pformat, (uintmax_t) ST_NBLOCKS (*statbuf));
break;
case 'o':
strcat (pformat, "lu");
xstrcat (pformat, buf_len, "lu");
printf (pformat, (unsigned long int) statbuf->st_blksize);
break;
case 'x':
strcat (pformat, "s");
xstrcat (pformat, buf_len, "s");
printf (pformat, human_time (statbuf->st_atime,
TIMESPEC_NS (statbuf->st_atim)));
break;
case 'X':
strcat (pformat, TYPE_SIGNED (time_t) ? "ld" : "lu");
xstrcat (pformat, buf_len, TYPE_SIGNED (time_t) ? "ld" : "lu");
printf (pformat, (unsigned long int) statbuf->st_atime);
break;
case 'y':
strcat (pformat, "s");
xstrcat (pformat, buf_len, "s");
printf (pformat, human_time (statbuf->st_mtime,
TIMESPEC_NS (statbuf->st_mtim)));
break;
case 'Y':
strcat (pformat, TYPE_SIGNED (time_t) ? "ld" : "lu");
xstrcat (pformat, buf_len, TYPE_SIGNED (time_t) ? "ld" : "lu");
printf (pformat, (unsigned long int) statbuf->st_mtime);
break;
case 'z':
strcat (pformat, "s");
xstrcat (pformat, buf_len, "s");
printf (pformat, human_time (statbuf->st_ctime,
TIMESPEC_NS (statbuf->st_ctim)));
break;
case 'Z':
strcat (pformat, TYPE_SIGNED (time_t) ? "ld" : "lu");
xstrcat (pformat, buf_len, TYPE_SIGNED (time_t) ? "ld" : "lu");
printf (pformat, (unsigned long int) statbuf->st_ctime);
break;
default:
strcat (pformat, "c");
xstrcat (pformat, buf_len, "c");
printf (pformat, m);
break;
}
@@ -526,7 +540,7 @@ print_stat (char *pformat, char m, char const *filename, void const *data)
static void
print_it (char const *masterformat, char const *filename,
void (*print_func) (char *, char, char const *, void const *),
void (*print_func) (char *, size_t, char, char const *, void const *),
void const *data)
{
char *b;
@@ -534,7 +548,10 @@ print_it (char const *masterformat, char const *filename,
/* create a working copy of the format string */
char *format = xstrdup (masterformat);
char *dest = xmalloc (strlen (format) + 2 + 1);
/* Add 2 to accommodate our conversion of the stat `%s' format string
to the printf `%llu' one. */
size_t n_alloc = strlen (format) + 2 + 1;
char *dest = xmalloc (n_alloc);
b = format;
while (b)
@@ -562,7 +579,7 @@ print_it (char const *masterformat, char const *filename,
putchar ('%');
break;
default:
print_func (dest, *p, filename, data);
print_func (dest, n_alloc, *p, filename, data);
break;
}
}