summaryrefslogtreecommitdiffstats
path: root/patches/source/glibc/glibc.CVE-2009-5029.diff
blob: 5c730d4218da20ef551a7a104371a4e9aa00cadf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
2011-12-17  Ulrich Drepper  <drepper@gmail.com>

	[BZ #13506]
	* time/tzfile.c (__tzfile_read): Check values from file header.

diff --git a/time/tzfile.c b/time/tzfile.c
index 144e20b..402389c 100644
--- a/time/tzfile.c
+++ b/time/tzfile.c
@@ -26,6 +26,7 @@
 #include <time.h>
 #include <unistd.h>
 #include <sys/stat.h>
+#include <stdint.h>
 
 #define	NOID
 #include <timezone/tzfile.h>
@@ -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_len == 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.  */