[tz] [PROPOSED PATCH 4/4] zdump: Don't silently truncate too-long abbreviations.
Paul Eggert
eggert at cs.ucla.edu
Thu Aug 21 21:43:26 UTC 2014
Instead, allocate a longer buffer, exiting if memory is exhausted.
* zdump.c (abbrev, abbrevsize, loab, loabsize): New static vars.
(saveabbr): New function.
(main, loab): Use the new function and variables.
(abbr): Arg is now a pointer-to-const, for saveabbr.
---
zdump.c | 48 +++++++++++++++++++++++++++++++++++++-----------
1 file changed, 37 insertions(+), 11 deletions(-)
diff --git a/zdump.c b/zdump.c
index f5a4dff..76b3453 100644
--- a/zdump.c
+++ b/zdump.c
@@ -212,7 +212,7 @@ static char * progname;
static bool warned;
static bool errout;
-static char *abbr(struct tm *);
+static char *abbr(struct tm const *);
static intmax_t delta(struct tm *, struct tm *) ATTRIBUTE_PURE;
static void dumptime(struct tm const *);
static time_t hunt(char *, time_t, time_t);
@@ -359,6 +359,36 @@ abbrok(const char *const abbrp, const char *const zone)
warned = errout = true;
}
+/* Extensible buffers for time zone abbreviations of the current and
+ low-boundary probes. */
+static char *abbrev;
+static size_t abbrevsize;
+static char *loab;
+static size_t loabsize;
+
+/* Save into *BUF (of size *BUFALLOC) the time zone abbreviation of TMP.
+ Exit on memory allocation failure. */
+static void
+saveabbr(char **buf, size_t *bufalloc, struct tm const *tmp)
+{
+ char const *ab = abbr(tmp);
+ size_t ablen = strlen(ab);
+ if (*bufalloc <= ablen) {
+ free(*buf);
+
+ /* Make the new buffer at least twice as long as the old,
+ to avoid O(N**2) behavior on repeated calls. */
+ *bufalloc = sumsize(*bufalloc, ablen + 1);
+
+ *buf = malloc(*bufalloc);
+ if (! *buf) {
+ perror(progname);
+ exit(EXIT_FAILURE);
+ }
+ }
+ strcpy(*buf, ab);
+}
+
static void
close_file(FILE *stream)
{
@@ -500,8 +530,6 @@ main(int argc, char *argv[])
}
for (i = optind; i < argc; ++i) {
- static char buf[MAX_STRING_LENGTH];
-
settimezone(argv[i]);
if (! (vflag | Vflag)) {
show(argv[i], now, false);
@@ -519,7 +547,7 @@ main(int argc, char *argv[])
tmp = my_localtime(&t);
if (tmp != NULL) {
tm = *tmp;
- strncpy(buf, abbr(&tm), (sizeof buf) - 1);
+ saveabbr(&abbrev, &abbrevsize, &tm);
}
for ( ; ; ) {
newt = (t < absolute_max_time - SECSPERDAY / 2
@@ -533,14 +561,13 @@ main(int argc, char *argv[])
if ((tmp == NULL || newtmp == NULL) ? (tmp != newtmp) :
(delta(&newtm, &tm) != (newt - t) ||
newtm.tm_isdst != tm.tm_isdst ||
- strcmp(abbr(&newtm), buf) != 0)) {
+ strcmp(abbr(&newtm), abbrev) != 0)) {
newt = hunt(argv[i], t, newt);
newtmp = localtime(&newt);
if (newtmp != NULL) {
newtm = *newtmp;
- strncpy(buf,
- abbr(&newtm),
- (sizeof buf) - 1);
+ saveabbr(&abbrev, &abbrevsize,
+ &newtm);
}
}
t = newt;
@@ -612,12 +639,11 @@ hunt(char *name, time_t lot, time_t hit)
register struct tm * lotmp;
struct tm tm;
register struct tm * tmp;
- char loab[MAX_STRING_LENGTH];
lotmp = my_localtime(&lot);
if (lotmp != NULL) {
lotm = *lotmp;
- strncpy(loab, abbr(&lotm), (sizeof loab) - 1);
+ saveabbr(&loab, &loabsize, &lotm);
}
for ( ; ; ) {
time_t diff = hit - lot;
@@ -705,7 +731,7 @@ show(char *zone, time_t t, bool v)
}
static char *
-abbr(struct tm *tmp)
+abbr(struct tm const *tmp)
{
register char * result;
static char nada;
--
1.9.1
More information about the tz
mailing list