about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@gmail.com>2011-12-17 20:18:42 -0500
committerUlrich Drepper <drepper@gmail.com>2011-12-17 20:18:42 -0500
commit97ac2654b2d831acaa18a2b018b0736245903fd2 (patch)
tree1cbd1360431dcd1a7f5dd77151ecefe6efd95920
parentb813d73fd7bb94390b787e86138c1169b64ca1ff (diff)
downloadglibc-97ac2654b2d831acaa18a2b018b0736245903fd2.tar.gz
glibc-97ac2654b2d831acaa18a2b018b0736245903fd2.tar.xz
glibc-97ac2654b2d831acaa18a2b018b0736245903fd2.zip
Check values from TZ file header
-rw-r--r--ChangeLog5
-rw-r--r--NEWS2
-rw-r--r--time/tzfile.c53
3 files changed, 50 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 4aad7eec6e..93f8760812 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2011-12-17  Ulrich Drepper  <drepper@gmail.com>
+
+	[BZ #13506]
+	* time/tzfile.c (__tzfile_read): Check values from file header.
+
 2011-11-21  Will Schmidt  <will_schmidt@vnet.ibm.com>
 
 	* powerpc/powerpc32/sysdep.h: Define SETUP_GOT_ACCESS() macro.
diff --git a/NEWS b/NEWS
index 241a4e9d98..6e0c1d7e7c 100644
--- a/NEWS
+++ b/NEWS
@@ -12,7 +12,7 @@ Version 2.15
   6779, 6783, 9696, 10103, 10709, 11589, 12403, 12847, 12868, 12852, 12874,
   12885, 12892, 12907, 12922, 12935, 13007, 13021, 13067, 13068, 13090,
   13092, 13114, 13118, 13123, 13134, 13138, 13147, 13150, 13179, 13192,
-  13268, 13276, 13291, 13335, 13337, 13344, 13358, 13367
+  13268, 13276, 13291, 13335, 13337, 13344, 13358, 13367, 13506
 
 * New program pldd to list loaded object of a process
   Implemented by Ulrich Drepper.
diff --git a/time/tzfile.c b/time/tzfile.c
index 144e20ba2e..402389c9f3 100644
--- a/time/tzfile.c
+++ b/time/tzfile.c
@@ -234,23 +234,58 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
       goto read_again;
     }
 
+  if (__builtin_expect (num_transitions
+			> ((SIZE_MAX - (__alignof__ (struct ttinfo) - 1))
+			   / (sizeof (time_t) + 1)), 0))
+    goto lose;
   total_size = num_transitions * (sizeof (time_t) + 1);
   total_size = ((total_size + __alignof__ (struct ttinfo) - 1)
 		& ~(__alignof__ (struct ttinfo) - 1));
   types_idx = total_size;
-  total_size += num_types * sizeof (struct ttinfo) + chars;
+  if (__builtin_expect (num_types
+			> (SIZE_MAX - total_size) / sizeof (struct ttinfo), 0))
+    goto lose;
+  total_size += num_types * sizeof (struct ttinfo);
+  if (__builtin_expect (chars > SIZE_MAX - total_size, 0))
+    goto lose;
+  total_size += chars;
+  if (__builtin_expect (__alignof__ (struct leap) - 1
+			> SIZE_MAX - total_size, 0))
+    goto lose;
   total_size = ((total_size + __alignof__ (struct leap) - 1)
 		& ~(__alignof__ (struct leap) - 1));
   leaps_idx = total_size;
+  if (__builtin_expect (num_leaps
+			> (SIZE_MAX - total_size) / sizeof (struct leap), 0))
+    goto lose;
   total_size += num_leaps * sizeof (struct leap);
-  tzspec_len = (sizeof (time_t) == 8 && trans_width == 8
-		? st.st_size - (ftello (f)
-				+ num_transitions * (8 + 1)
-				+ num_types * 6
-				+ chars
-				+ num_leaps * 12
-				+ num_isstd
-				+ num_isgmt) - 1 : 0);
+  tzspec_len = 0;
+  if (sizeof (time_t) == 8 && trans_width == 8)
+    {
+      off_t rem = st.st_size - ftello (f);
+      if (__builtin_expect (rem < 0
+			    || (size_t) rem < (num_transitions * (8 + 1)
+					       + num_types * 6
+					       + chars), 0))
+	goto lose;
+      tzspec_len = (size_t) rem - (num_transitions * (8 + 1)
+				   + num_types * 6
+				   + chars);
+      if (__builtin_expect (num_leaps > SIZE_MAX / 12
+			    || tzspec_len < num_leaps * 12, 0))
+	goto lose;
+      tzspec_len -= num_leaps * 12;
+      if (__builtin_expect (tzspec_len < num_isstd, 0))
+	goto lose;
+      tzspec_len -= num_isstd;
+      if (__builtin_expect (tzspec == 0 || tzspec_len - 1 < num_isgmt, 0))
+	goto lose;
+      tzspec_len -= num_isgmt + 1;
+      if (__builtin_expect (SIZE_MAX - total_size < tzspec_len, 0))
+	goto lose;
+    }
+  if (__builtin_expect (SIZE_MAX - total_size - tzspec_len < extra, 0))
+    goto lose;
 
   /* Allocate enough memory including the extra block requested by the
      caller.  */