[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
ls.c patch to avoid generating way-too-long time stamps
From: |
Paul Eggert |
Subject: |
ls.c patch to avoid generating way-too-long time stamps |
Date: |
Fri, 11 Mar 2005 15:15:58 -0800 |
User-agent: |
Gnus/5.1006 (Gnus v5.10.6) Emacs/21.4 (gnu/linux) |
I installed this:
2005-03-11 Paul Eggert <address@hidden>
* src/ls.c (TIME_STAMP_LEN_MAXIMUM): New constant.
(long_time_expected_width, print_long_format): Use it, to avoid
some possible denial-of-service attacks.
* NEWS: Document this.
* doc/coreutils.texi (Formatting file timestamps): Likewise.
Index: NEWS
===================================================================
RCS file: /fetish/cu/NEWS,v
retrieving revision 1.271
diff -p -u -r1.271 NEWS
--- NEWS 28 Feb 2005 10:18:32 -0000 1.271
+++ NEWS 11 Mar 2005 23:12:10 -0000
@@ -27,6 +27,9 @@ GNU coreutils NEWS
expr now detects integer overflow when evaluating large integers,
rather than silently wrapping around.
+ ls now refuses to generate time stamps containing more than 1000 bytes, to
+ foil remote denial-of-service attacks (e.g., --time-style='+%1000000000Y').
+
test now detects integer overflow when evaluating large integers,
rather than silently wrapping around.
Index: doc/coreutils.texi
===================================================================
RCS file: /fetish/cu/doc/coreutils.texi,v
retrieving revision 1.243
diff -p -u -r1.243 coreutils.texi
--- doc/coreutils.texi 8 Mar 2005 22:19:39 -0000 1.243
+++ doc/coreutils.texi 11 Mar 2005 23:12:12 -0000
@@ -6073,6 +6073,9 @@ later can parse @acronym{ISO} dates, but
you are using an older version of Emacs and specify a address@hidden
locale, you may need to set @samp{TIME_STYLE="locale"}.
+To avoid certain denial-of-service attacks, timestamps that would be
+longer than 1000 bytes may be treated as errors.
+
@node Formatting the file names
@subsection Formatting the file names
Index: src/ls.c
===================================================================
RCS file: /fetish/cu/src/ls.c,v
retrieving revision 1.376
diff -p -u -r1.376 ls.c
--- src/ls.c 10 Mar 2005 12:07:31 -0000 1.376
+++ src/ls.c 11 Mar 2005 23:12:12 -0000
@@ -643,6 +643,14 @@ static bool format_needs_stat;
static bool format_needs_type;
+/* An arbitrary limit on the number of bytes in a printed time stamp.
+ This is set to a relatively small value to avoid the need to worry
+ about denial-of-service attacks on servers that run "ls" on behalf
+ of remote clients. 1000 bytes should be enough for any practical
+ time stamp format. */
+
+enum { TIME_STAMP_LEN_MAXIMUM = MAX (1000, INT_STRLEN_BOUND (time_t)) };
+
/* strftime formats for non-recent and recent files, respectively, in
-l output. */
@@ -3047,32 +3055,18 @@ long_time_expected_width (void)
{
time_t epoch = 0;
struct tm const *tm = localtime (&epoch);
- char const *fmt = long_time_format[0];
- char initbuf[100];
- char *buf = initbuf;
- size_t bufsize = sizeof initbuf;
- size_t len;
-
- for (;;)
- {
- *buf = '\1';
- len = nstrftime (buf, bufsize, fmt, tm, 0, 0);
- if (len || ! *buf)
- break;
- if (buf == initbuf)
- {
- buf = NULL;
- bufsize *= 2;
- }
- buf = x2nrealloc (buf, &bufsize, sizeof *buf);
+ char buf[TIME_STAMP_LEN_MAXIMUM + 1];
+
+ if (tm)
+ {
+ size_t len =
+ nstrftime (buf, sizeof buf, long_time_format[0], tm, 0, 0);
+ if (len != 0)
+ width = mbsnwidth (buf, len, 0);
}
- width = mbsnwidth (buf, len, 0);
if (width < 0)
width = 0;
-
- if (buf != initbuf)
- free (buf);
}
return width;
@@ -3200,17 +3194,15 @@ static void
print_long_format (const struct fileinfo *f)
{
char modebuf[12];
- char init_bigbuf
+ char buf
[LONGEST_HUMAN_READABLE + 1 /* inode */
+ LONGEST_HUMAN_READABLE + 1 /* size in blocks */
+ sizeof (modebuf) - 1 + 1 /* mode string */
+ INT_BUFSIZE_BOUND (uintmax_t) /* st_nlink */
+ LONGEST_HUMAN_READABLE + 2 /* major device number */
+ LONGEST_HUMAN_READABLE + 1 /* minor device number */
- + 35 + 1 /* usual length of time/date -- may be longer; see below */
+ + TIME_STAMP_LEN_MAXIMUM + 1 /* max length of time/date */
];
- char *buf = init_bigbuf;
- size_t bufsize = sizeof (init_bigbuf);
size_t s;
char *p;
time_t when;
@@ -3320,7 +3312,11 @@ print_long_format (const struct fileinfo
p[-1] = ' ';
}
- if ((when_local = localtime (&when)))
+ when_local = localtime (&when);
+ s = 0;
+ *p = '\1';
+
+ if (when_local)
{
time_t six_months_ago;
bool recent;
@@ -3349,28 +3345,12 @@ print_long_format (const struct fileinfo
|| (when == current_time && when_ns <= current_time_ns)));
fmt = long_time_format[recent];
- for (;;)
- {
- char *newbuf;
- *p = '\1';
- s = nstrftime (p, buf + bufsize - p - 1, fmt,
- when_local, 0, when_ns);
- if (s || ! *p)
- break;
- if (buf == init_bigbuf)
- {
- bufsize *= 2;
- newbuf = xmalloc (bufsize);
- memcpy (newbuf, buf, p - buf);
- }
- else
- {
- newbuf = x2nrealloc (buf, &bufsize, sizeof *buf);
- }
- p = newbuf + (p - buf);
- buf = newbuf;
- }
+ s = nstrftime (p, TIME_STAMP_LEN_MAXIMUM + 1, fmt,
+ when_local, 0, when_ns);
+ }
+ if (s || !*p)
+ {
p += s;
*p++ = ' ';
@@ -3379,7 +3359,7 @@ print_long_format (const struct fileinfo
}
else
{
- /* The time cannot be represented as a local time;
+ /* The time cannot be converted using the desired format, so
print it as a huge integer number of seconds. */
char hbuf[INT_BUFSIZE_BOUND (intmax_t)];
sprintf (p, "%*s ", long_time_expected_width (),
@@ -3390,8 +3370,6 @@ print_long_format (const struct fileinfo
}
DIRED_FPUTS (buf, stdout, p - buf);
- if (buf != init_bigbuf)
- free (buf);
print_name_with_quoting (f->name, FILE_OR_LINK_MODE (f), f->linkok,
&dired_obstack);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- ls.c patch to avoid generating way-too-long time stamps,
Paul Eggert <=