about summary refs log tree commit diff
path: root/time/tzfile.c
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2015-04-24 17:34:47 +0200
committerFlorian Weimer <fweimer@redhat.com>2015-04-24 17:34:48 +0200
commit42261ad731991df345880b0b509d83b0b9a9b9d8 (patch)
tree440bf43dca45a9002402ec602f0deaf3bfa6e3e3 /time/tzfile.c
parented159672eb3cd650a32b7e5cb4d5ec1fe0e63802 (diff)
downloadglibc-42261ad731991df345880b0b509d83b0b9a9b9d8.tar.gz
glibc-42261ad731991df345880b0b509d83b0b9a9b9d8.tar.xz
glibc-42261ad731991df345880b0b509d83b0b9a9b9d8.zip
Make time zone file parser more robust [BZ #17715]
Diffstat (limited to 'time/tzfile.c')
-rw-r--r--time/tzfile.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/time/tzfile.c b/time/tzfile.c
index bcb408fcdb..46d4fc71ae 100644
--- a/time/tzfile.c
+++ b/time/tzfile.c
@@ -200,6 +200,9 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
   num_isstd = (size_t) decode (tzhead.tzh_ttisstdcnt);
   num_isgmt = (size_t) decode (tzhead.tzh_ttisgmtcnt);
 
+  if (__glibc_unlikely (num_isstd > num_types || num_isgmt > num_types))
+    goto lose;
+
   /* For platforms with 64-bit time_t we use the new format if available.  */
   if (sizeof (time_t) == 8 && trans_width == 4
       && tzhead.tzh_version[0] != '\0')
@@ -434,13 +437,21 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
 	goto lose;
 
       tzspec_len = st.st_size - off - 1;
-      char *tzstr = alloca (tzspec_len);
+      if (tzspec_len == 0)
+	goto lose;
+      char *tzstr = malloc (tzspec_len);
+      if (tzstr == NULL)
+	goto lose;
       if (getc_unlocked (f) != '\n'
 	  || (__fread_unlocked (tzstr, 1, tzspec_len - 1, f)
 	      != tzspec_len - 1))
-	goto lose;
+	{
+	  free (tzstr);
+	  goto lose;
+	}
       tzstr[tzspec_len - 1] = '\0';
       tzspec = __tzstring (tzstr);
+      free (tzstr);
     }
 
   /* Don't use an empty TZ string.  */