about summary refs log tree commit diff
diff options
context:
space:
mode:
-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.  */