[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#7325: new test failure due to non-portability of printf formats like
From: |
Paul Eggert |
Subject: |
bug#7325: new test failure due to non-portability of printf formats like %05.3s |
Date: |
Wed, 03 Nov 2010 15:58:25 -0700 |
User-agent: |
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.15) Gecko/20101027 Thunderbird/3.0.10 |
The test-case part of that looks OK, but the change to stat.c
can be simplified. Also, there's a similar problem with a format
like %020X, which should be fixed too.
While we're on the subject, there are other ways that stat invokers
can exercise undefined behavior (in the C sense) by passing
weird formats in. This really should get fixed at some point.
The patch proposed below addresses just the immediate issue.
>From a24a9ce8f3711670a6413c60b5e9ebd3e51a4e06 Mon Sep 17 00:00:00 2001
From: Paul Eggert <address@hidden>
Date: Wed, 3 Nov 2010 15:49:50 -0700
Subject: [PATCH] stat: handle leading '0' when formatting secs and ns
* src/stat.c (epoch_sec): Remove. All callers changed to use
out_epoch_sec instead.
(out_ns): Use numeric format, not string format, to output
the nanoseconds count; this avoids unportable use of (e.g.)
%05s in a printf format.
(out_epoch_sec): New function. This also uses a numeric format,
instead of a string format, to output a number.
---
src/stat.c | 56 ++++++++++++++++++++++++++++++++++++--------------------
1 files changed, 36 insertions(+), 20 deletions(-)
diff --git a/src/stat.c b/src/stat.c
index d05a93b..c1def13 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -463,15 +463,6 @@ human_time (struct timespec t)
return str;
}
-/* Return a string representation (in static storage)
- of the number of seconds in T since the epoch. */
-static char * ATTRIBUTE_WARN_UNUSED_RESULT
-epoch_sec (struct timespec t)
-{
- static char str[INT_BUFSIZE_BOUND (time_t)];
- return timetostr (t.tv_sec, str);
-}
-
/* Output the number of nanoseconds, ARG.tv_nsec, honoring a
WIDTH.PRECISION format modifier, where PRECISION specifies
how many leading digits(on a field of 9) to print. */
@@ -491,13 +482,29 @@ out_ns (char *pformat, size_t prefix_len, struct timespec
arg)
on the default representation, i.e., a zero padded number
of width 9. */
unsigned long int ns = arg.tv_nsec;
+ char *dot = memchr (pformat, '.', prefix_len);
- if (memchr (pformat, '.', prefix_len)) /* precision specified. */
+ if (dot)
{
- char tmp[INT_BUFSIZE_BOUND (uintmax_t)];
- snprintf (tmp, sizeof tmp, "%09lu", ns);
- strcpy (pformat + prefix_len, "s");
- printf (pformat, tmp);
+ /* Precision specified. */
+ size_t i;
+ int precision = 0;
+ for (i = dot - pformat + 1; i < prefix_len && ISDIGIT (pformat[i]); i++)
+ {
+ if (! precision)
+ precision = pformat[i] - '0';
+ else
+ {
+ /* If more than 9 digits are asked for, just output 9. */
+ precision = 9;
+ break;
+ }
+ }
+ if (! precision)
+ return;
+ for (; precision < 9; precision++)
+ ns /= 10;
+ strcpy (dot, "lu");
}
else
{
@@ -505,8 +512,9 @@ out_ns (char *pformat, size_t prefix_len, struct timespec
arg)
/* Note that pformat is big enough, as %:X -> %09lu
and two extra bytes are already allocated. */
strcpy (pformat + prefix_len, fmt);
- printf (pformat, ns);
}
+
+ printf (pformat, ns);
}
static void
@@ -539,6 +547,14 @@ out_uint_x (char *pformat, size_t prefix_len, uintmax_t
arg)
strcpy (pformat + prefix_len, PRIxMAX);
printf (pformat, arg);
}
+static void
+out_epoch_sec (char *pformat, size_t prefix_len, struct timespec arg)
+{
+ if (TYPE_SIGNED (time_t))
+ out_int (pformat, prefix_len, arg.tv_sec);
+ else
+ out_uint (pformat, prefix_len, arg.tv_sec);
+}
/* Print the context information of FILENAME, and return true iff the
context could not be obtained. */
@@ -853,8 +869,8 @@ print_stat (char *pformat, size_t prefix_len, unsigned int
m,
}
break;
case 'W':
- out_string (pformat, prefix_len,
- epoch_sec (neg_to_zero (get_stat_birthtime (statbuf))));
+ out_epoch_sec (pformat, prefix_len,
+ neg_to_zero (get_stat_birthtime (statbuf)));
break;
case 'W' + 256:
out_ns (pformat, prefix_len, neg_to_zero (get_stat_birthtime (statbuf)));
@@ -863,7 +879,7 @@ print_stat (char *pformat, size_t prefix_len, unsigned int
m,
out_string (pformat, prefix_len, human_time (get_stat_atime (statbuf)));
break;
case 'X':
- out_string (pformat, prefix_len, epoch_sec (get_stat_atime (statbuf)));
+ out_epoch_sec (pformat, prefix_len, get_stat_atime (statbuf));
break;
case 'X' + 256:
out_ns (pformat, prefix_len, get_stat_atime (statbuf));
@@ -872,7 +888,7 @@ print_stat (char *pformat, size_t prefix_len, unsigned int
m,
out_string (pformat, prefix_len, human_time (get_stat_mtime (statbuf)));
break;
case 'Y':
- out_string (pformat, prefix_len, epoch_sec (get_stat_mtime (statbuf)));
+ out_epoch_sec (pformat, prefix_len, get_stat_mtime (statbuf));
break;
case 'Y' + 256:
out_ns (pformat, prefix_len, get_stat_mtime (statbuf));
@@ -881,7 +897,7 @@ print_stat (char *pformat, size_t prefix_len, unsigned int
m,
out_string (pformat, prefix_len, human_time (get_stat_ctime (statbuf)));
break;
case 'Z':
- out_string (pformat, prefix_len, epoch_sec (get_stat_ctime (statbuf)));
+ out_epoch_sec (pformat, prefix_len, get_stat_ctime (statbuf));
break;
case 'Z' + 256:
out_ns (pformat, prefix_len, get_stat_ctime (statbuf));
--
1.7.2
- bug#7325: new test failure due to non-portability of printf formats like %05.3s, Jim Meyering, 2010/11/03
- bug#7325: new test failure due to non-portability of printf formats like %05.3s, Eric Blake, 2010/11/03
- bug#7325: new test failure due to non-portability of printf formats like %05.3s, Jim Meyering, 2010/11/03
- bug#7325: new test failure due to non-portability of printf formats like %05.3s, Eric Blake, 2010/11/03
- bug#7325: new test failure due to non-portability of printf formats like %05.3s,
Paul Eggert <=
- bug#7325: new test failure due to non-portability of printf formats like %05.3s, Jim Meyering, 2010/11/04
- bug#7325: new test failure due to non-portability of printf formats like %05.3s, Jim Meyering, 2010/11/04
- bug#7325: new test failure due to non-portability of printf formats like %05.3s, Paul Eggert, 2010/11/04
- bug#7325: new test failure due to non-portability of printf formats like %05.3s, Jim Meyering, 2010/11/04
- bug#7325: new test failure due to non-portability of printf formats like %05.3s, Jim Meyering, 2010/11/05
- bug#7325: new test failure due to non-portability of printf formats like %05.3s, Paul Eggert, 2010/11/05
- bug#7325: new test failure due to non-portability of printf formats like %05.3s, Pádraig Brady, 2010/11/04
- bug#7325: new test failure due to non-portability of printf formats like %05.3s, Jim Meyering, 2010/11/05
- bug#7325: new test failure due to non-portability of printf formats like %05.3s, Paul Eggert, 2010/11/05
- bug#7325: new test failure due to non-portability of printf formats like %05.3s, Jim Meyering, 2010/11/06