* NEWS: Mention this.
* localtime.c (tzloadbody): If the TZif file’s TZ string would
exceed our abbreviation capacity, return EOVERFLOW rather than
silently misbehaving.
---
 NEWS        |  4 ++++
 localtime.c | 14 +++++++-------
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/NEWS b/NEWS
index 513ca2c7..35696fcb 100644
--- a/NEWS
+++ b/NEWS
@@ -52,6 +52,10 @@ Unreleased, experimental changes
     zic now ports to systems that report lack of link support via
     EINVAL, ENOSYS or EPERM errno values. (Thanks to Tom Lane.)
 
+    When tzset and related functions encounter a TZif file that is too
+    large for them, they now consistently fail instead of sometimes
+    silently ignoring excess parts of the file.
+
   Changes to documentation
 
     URLs for release tarballs in tz-link.html have been updated to
diff --git a/localtime.c b/localtime.c
index 20e88c35..8044f1a0 100644
--- a/localtime.c
+++ b/localtime.c
@@ -1246,7 +1246,6 @@ tzloadbody(char const *name, struct state *sp, char 
tzloadflags,
                             AHDT YST AKDT AKST) and ts->charcnt equals 10
                             (for AKST AKDT).  Reusing means sp->charcnt can
                             stay 40 in this example.  */
-                         int gotabbr = 0;
                          int charcnt = sp->charcnt;
                          for (i = 0; i < ts->typecnt; i++) {
                            char *tsabbr = ts->chars + ts->ttis[i].tt_desigidx;
@@ -1254,24 +1253,25 @@ tzloadbody(char const *name, struct state *sp, char 
tzloadflags,
                            for (j = 0; j < charcnt; j++)
                              if (strcmp(sp->chars + j, tsabbr) == 0) {
                                ts->ttis[i].tt_desigidx = j;
-                               gotabbr++;
                                break;
                              }
                            if (! (j < charcnt)) {
                              int tsabbrlen = strnlen(tsabbr, TZ_MAX_CHARS - j);
-                             if (j + tsabbrlen < TZ_MAX_CHARS) {
+                             if (TZ_MAX_CHARS <= j + tsabbrlen)
+                               return EOVERFLOW;
+                             else {
                                char *cp = sp->chars + j;
                                cp = mempcpy(cp, tsabbr, tsabbrlen);
                                *cp = '\0';
                                charcnt = j + tsabbrlen + 1;
                                ts->ttis[i].tt_desigidx = j;
-                               gotabbr++;
                              }
                            }
                          }
-                         if (gotabbr == ts->typecnt) {
-                           if (TZ_MAX_TYPES - sp->typecnt < ts->typecnt)
-                             return EOVERFLOW;
+
+                         if (TZ_MAX_TYPES - sp->typecnt < ts->typecnt)
+                           return EOVERFLOW;
+                         else {
                            sp->charcnt = charcnt;
 
                            /* Ignore any trailing, no-op transitions generated
-- 
2.55.0

Reply via email to