aboutsummaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-support/mysql/mariadb/fix-cve-2013-1861-2.patch
blob: c35cdfb6413ab1de44cd79667b3b8cb97e5962cd (plain)
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
From 9f714cdd3bf4bd8ee06cd38dcd2c6e8990a4ec48 Mon Sep 17 00:00:00 2001
From: Alexey Botchkov <holyfoot@askmonty.org>
Date: Mon, 18 Mar 2013 17:58:00 +0400
Subject: [PATCH] MDEV-4252 geometry query crashes server.     Additional fixes
 for possible overflows in length-related     calculations in 'spatial'
 implementations.     Checks added to the ::get_data_size() methods.    
 max_n_points decreased to occupy less 2G size. An     object of that size is
 practically inoperable anyway.

Upstream-Status: Backport
Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>

---
 mysql-test/r/gis.result | 12 +++++++++
 mysql-test/t/gis.test   |  6 +++++
 sql/spatial.cc          | 67 ++++++++++++++++++++++++++++++++++---------------
 sql/spatial.h           |  2 +-
 4 files changed, 66 insertions(+), 21 deletions(-)

diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result
index 69e73d0..7566f0b 100644
--- a/mysql-test/r/gis.result
+++ b/mysql-test/r/gis.result
@@ -1087,7 +1087,19 @@ NULL
 #
 SELECT GEOMETRYCOLLECTION((SELECT @@OLD));
 ERROR 22007: Illegal non geometric '' value found during parsing
+#
+# MDEV-4252 geometry query crashes server
+#
 select astext(0x0100000000030000000100000000000010);
 astext(0x0100000000030000000100000000000010)
 NULL
+select envelope(0x0100000000030000000100000000000010);
+envelope(0x0100000000030000000100000000000010)
+NULL
+select geometryn(0x0100000000070000000100000001030000000200000000000000ffff0000, 1);
+geometryn(0x0100000000070000000100000001030000000200000000000000ffff0000, 1)
+NULL
+select geometryn(0x0100000000070000000100000001030000000200000000000000ffffff0f, 1);
+geometryn(0x0100000000070000000100000001030000000200000000000000ffffff0f, 1)
+NULL
 End of 5.1 tests
diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test
index cc5d158..c42541e 100644
--- a/mysql-test/t/gis.test
+++ b/mysql-test/t/gis.test
@@ -826,6 +826,12 @@ SELECT ISCLOSED(CONVERT(CONCAT('     ', 0x2), BINARY(20)));
 --error ER_ILLEGAL_VALUE_FOR_TYPE
 SELECT GEOMETRYCOLLECTION((SELECT @@OLD));
 
+--echo #
+--echo # MDEV-4252 geometry query crashes server
+--echo #
 select astext(0x0100000000030000000100000000000010);
+select envelope(0x0100000000030000000100000000000010);
+select geometryn(0x0100000000070000000100000001030000000200000000000000ffff0000, 1);
+select geometryn(0x0100000000070000000100000001030000000200000000000000ffffff0f, 1);
 
 --echo End of 5.1 tests
diff --git a/sql/spatial.cc b/sql/spatial.cc
index 94d0238..5a4b768 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -394,18 +394,19 @@ const char *Geometry::append_points(String *txt, uint32 n_points,
 const char *Geometry::get_mbr_for_points(MBR *mbr, const char *data,
 					 uint offset) const
 {
-  uint32 points;
+  uint32 n_points;
   /* read number of points */
   if (no_data(data, 4))
     return 0;
-  points= uint4korr(data);
+  n_points= uint4korr(data);
   data+= 4;
 
-  if (no_data(data, (SIZEOF_STORED_DOUBLE * 2 + offset) * points))
+  if (n_points > max_n_points ||
+      no_data(data, (POINT_DATA_SIZE + offset) * n_points))
     return 0;
 
   /* Calculate MBR for points */
-  while (points--)
+  while (n_points--)
   {
     data+= offset;
     mbr->add_xy(data, data + SIZEOF_STORED_DOUBLE);
@@ -484,9 +485,12 @@ const Geometry::Class_info *Gis_point::get_class_info() const
 
 uint32 Gis_line_string::get_data_size() const 
 {
-  if (no_data(m_data, 4))
+  uint32 n_points, size;
+  if (no_data(m_data, 4) ||
+      (n_points= uint4korr(m_data)) > max_n_points ||
+      no_data(m_data, (size= 4 + n_points * POINT_DATA_SIZE)))
     return GET_SIZE_ERROR;
-  return 4 + uint4korr(m_data) * POINT_DATA_SIZE;
+  return size;
 }
 
 
@@ -665,6 +669,9 @@ int Gis_line_string::end_point(String *result) const
   if (no_data(m_data, 4))
     return 1;
   n_points= uint4korr(m_data);
+  if (n_points == 0 || n_points > max_n_points ||
+      no_data(m_data, POINT_DATA_SIZE * n_points))
+    return 1;
   return create_point(result, m_data + 4 + (n_points - 1) * POINT_DATA_SIZE);
 }
 
@@ -674,11 +681,14 @@ int Gis_line_string::point_n(uint32 num, String *result) const
   uint32 n_points;
   if (no_data(m_data, 4))
     return 1;
+  num--;
   n_points= uint4korr(m_data);
-  if ((uint32) (num - 1) >= n_points) // means (num > n_points || num < 1)
+  if (num >= n_points ||
+      num > max_n_points || // means (num > n_points || num < 1)
+      no_data(m_data, num * POINT_DATA_SIZE))
     return 1;
 
-  return create_point(result, m_data + 4 + (num - 1) * POINT_DATA_SIZE);
+  return create_point(result, m_data + 4 + num*POINT_DATA_SIZE);
 }
 
 const Geometry::Class_info *Gis_line_string::get_class_info() const
@@ -692,6 +702,7 @@ const Geometry::Class_info *Gis_line_string::get_class_info() const
 uint32 Gis_polygon::get_data_size() const 
 {
   uint32 n_linear_rings;
+  uint32 n_points;
   const char *data= m_data;
 
   if (no_data(data, 4))
@@ -701,10 +712,13 @@ uint32 Gis_polygon::get_data_size() const
 
   while (n_linear_rings--)
   {
-    if (no_data(data, 4))
+    if (no_data(data, 4) ||
+        (n_points= uint4korr(data)) > max_n_points)
       return GET_SIZE_ERROR;
-    data+= 4 + uint4korr(data)*POINT_DATA_SIZE;
+    data+= 4 + n_points*POINT_DATA_SIZE;
   }
+  if (no_data(data, 0))
+    return GET_SIZE_ERROR;
   return (uint32) (data - m_data);
 }
 
@@ -1037,9 +1051,14 @@ const Geometry::Class_info *Gis_polygon::get_class_info() const
 
 uint32 Gis_multi_point::get_data_size() const 
 {
-  if (no_data(m_data, 4))
-    return GET_SIZE_ERROR;
-  return 4 + uint4korr(m_data)*(POINT_DATA_SIZE + WKB_HEADER_SIZE);
+  uint32 n_points;
+  uint32 size;
+
+  if (no_data(m_data, 4) ||
+      (n_points= uint4korr(m_data)) > max_n_points ||
+      no_data(m_data, (size= 4 + n_points*(POINT_DATA_SIZE + WKB_HEADER_SIZE))))
+     return GET_SIZE_ERROR;
+  return size;
 }
 
 
@@ -1107,7 +1126,8 @@ bool Gis_multi_point::get_data_as_wkt(String *txt, const char **end) const
     return 1;
 
   n_points= uint4korr(m_data);
-  if (no_data(m_data+4,
+  if (n_points > max_n_points ||
+      no_data(m_data+4,
 	      n_points * (SIZEOF_STORED_DOUBLE * 2 + WKB_HEADER_SIZE)) ||
       txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
     return 1;
@@ -1160,6 +1180,7 @@ const Geometry::Class_info *Gis_multi_point::get_class_info() const
 uint32 Gis_multi_line_string::get_data_size() const 
 {
   uint32 n_line_strings;
+  uint32 n_points;
   const char *data= m_data;
 
   if (no_data(data, 4))
@@ -1169,11 +1190,13 @@ uint32 Gis_multi_line_string::get_data_size() const
 
   while (n_line_strings--)
   {
-    if (no_data(data, WKB_HEADER_SIZE + 4))
+    if (no_data(data, WKB_HEADER_SIZE + 4) ||
+        (n_points= uint4korr(data + WKB_HEADER_SIZE)) > max_n_points)
       return GET_SIZE_ERROR;
-    data+= (WKB_HEADER_SIZE + 4 + uint4korr(data + WKB_HEADER_SIZE) *
-	    POINT_DATA_SIZE);
+    data+= (WKB_HEADER_SIZE + 4 + n_points*POINT_DATA_SIZE);
   }
+  if (no_data(data, 0))
+    return GET_SIZE_ERROR;
   return (uint32) (data - m_data);
 }
 
@@ -1327,7 +1350,7 @@ int Gis_multi_line_string::geometry_n(uint32 num, String *result) const
       return 1;
     n_points= uint4korr(data + WKB_HEADER_SIZE);
     length= WKB_HEADER_SIZE + 4+ POINT_DATA_SIZE * n_points;
-    if (no_data(data, length))
+    if (n_points > max_n_points || no_data(data, length))
       return 1;
     if (!--num)
       break;
@@ -1407,6 +1430,7 @@ const Geometry::Class_info *Gis_multi_line_string::get_class_info() const
 uint32 Gis_multi_polygon::get_data_size() const 
 {
   uint32 n_polygons;
+  uint32 n_points;
   const char *data= m_data;
 
   if (no_data(data, 4))
@@ -1425,11 +1449,14 @@ uint32 Gis_multi_polygon::get_data_size() const
 
     while (n_linear_rings--)
     {
-      if (no_data(data, 4))
+      if (no_data(data, 4) ||
+          (n_points= uint4korr(data)) > max_n_points)
 	return GET_SIZE_ERROR;
-      data+= 4 + uint4korr(data) * POINT_DATA_SIZE;
+      data+= 4 + n_points * POINT_DATA_SIZE;
     }
   }
+  if (no_data(data, 0))
+    return GET_SIZE_ERROR;
   return (uint32) (data - m_data);
 }
 
diff --git a/sql/spatial.h b/sql/spatial.h
index 7d25425..d7632c1 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -199,7 +199,7 @@ class Geometry
 public:
   // Maximum number of points in feature that can fit into String
   static const uint32 max_n_points=
-    (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) /
+    (uint32) (INT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) /
     POINT_DATA_SIZE;
 public:
   Geometry() {}                               /* Remove gcc warning */
-- 
1.8.1.6