summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>1997-01-05 20:32:49 +0000
committerJim Meyering <jim@meyering.net>1997-01-05 20:32:49 +0000
commit5f0b9f1d998661fdff80c4a8eb4d46af1d68feea (patch)
tree908ad660cf6df3a7f67ae66539592d3ada4b5984 /src
parent8ebfd37293d06b69998937535535258e3938a107 (diff)
downloadcoreutils-5f0b9f1d998661fdff80c4a8eb4d46af1d68feea.tar.xz
(print_long_format): Detect and handle strftime failure
due to pathologically long strings in locale tables. Patch from Paul Eggert. (print_long_format): Change references to BIGBUF in use of FPUT macro to references to BUF. Use 11 (not 20) bytes for mode string buffer.
Diffstat (limited to 'src')
-rw-r--r--src/ls.c34
1 files changed, 23 insertions, 11 deletions
diff --git a/src/ls.c b/src/ls.c
index bd9462941..a69292e29 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -2034,16 +2034,17 @@ print_current_files (void)
static void
print_long_format (const struct fileinfo *f)
{
- char modebuf[20];
-/* This is more than enough for all known LC_TIME locales. */
-#define TIMEBUF_SIZE 100
+ char modebuf[11];
/* 7 fields that may (worst case: 64-bit integral values) require 20 bytes,
- 1 10-character mode string,
- 1 TIMEBUF_SIZE-character time string,
- 9 spaces, one following each of these fields,
- and 1 trailing NUL byte. */
- char bigbuf[7 * 20 + 10 + TIMEBUF_SIZE + 9 + 1];
+ 1 10-byte mode string,
+ 1 24-byte time string (may be longer in some locales -- see below),
+ 9 spaces, one following each of these fields, and
+ 1 trailing NUL byte. */
+ char init_bigbuf[7 * 20 + 10 + 24 + 9 + 1];
+ char *buf = init_bigbuf;
+ size_t bufsize = sizeof (init_bigbuf);
+ size_t s;
char *p;
time_t when;
const char *fmt;
@@ -2092,7 +2093,7 @@ print_long_format (const struct fileinfo *f)
}
}
- p = bigbuf;
+ p = buf;
if (print_inode)
{
@@ -2137,12 +2138,23 @@ print_long_format (const struct fileinfo *f)
/* Use strftime rather than ctime, because the former can produce
locale-dependent names for the weekday (%a) and month (%b). */
- p += strftime (p, TIMEBUF_SIZE, fmt, localtime (&when));
+
+ while (! (s = strftime (p, buf + bufsize - p, fmt, localtime (&when))))
+ {
+ char *newbuf = alloca (bufsize *= 2);
+ memcpy (newbuf, buf, p - buf);
+ p = newbuf + (p - buf);
+ buf = newbuf;
+ }
+
+ p += s;
*p++ = ' ';
+
+ /* NUL-terminate the string -- fputs (via FPUTS) requires it. */
*p = '\0';
DIRED_INDENT ();
- FPUTS (bigbuf, stdout, p - bigbuf);
+ FPUTS (buf, stdout, p - buf);
PUSH_CURRENT_DIRED_POS (&dired_obstack);
print_name_with_quoting (f->name, f->stat.st_mode, f->linkok);
PUSH_CURRENT_DIRED_POS (&dired_obstack);