aboutsummaryrefslogtreecommitdiffstats
path: root/meta-oe/recipes-support/mysql/mariadb/fix-cve-2013-1861-1.patch
blob: df2e7086c42bb44bf265164c82ecf0ce1cbde97c (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
From 24404044ad4c28026e400e1fcd85358f2060aa96 Mon Sep 17 00:00:00 2001
From: Alexey Botchkov <holyfoot@askmonty.org>
Date: Sun, 10 Mar 2013 23:08:05 +0400
Subject: [PATCH] MDEV-4252 geometry query crashes server.       The bug was
 found by Alyssa Milburn.       If the number of points of a geometry feature
 read from       binary representation is greater than 0x10000000, then      
 the (uint32) (num_points * 16) will cut the higher byte,       which leads to
 various errors.       Fixed by additional check if (num_points >
 max_n_points).

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

---
 mysql-test/r/gis.result |  3 +++
 mysql-test/t/gis.test   |  1 +
 sql/spatial.cc          | 27 ++++++++++++++++++---------
 sql/spatial.h           |  9 +++++----
 4 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result
index 8dad72f..69e73d0 100644
--- a/mysql-test/r/gis.result
+++ b/mysql-test/r/gis.result
@@ -1087,4 +1087,7 @@ NULL
 #
 SELECT GEOMETRYCOLLECTION((SELECT @@OLD));
 ERROR 22007: Illegal non geometric '' value found during parsing
+select astext(0x0100000000030000000100000000000010);
+astext(0x0100000000030000000100000000000010)
+NULL
 End of 5.1 tests
diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test
index abda3e9..cc5d158 100644
--- a/mysql-test/t/gis.test
+++ b/mysql-test/t/gis.test
@@ -826,5 +826,6 @@ SELECT ISCLOSED(CONVERT(CONCAT('     ', 0x2), BINARY(20)));
 --error ER_ILLEGAL_VALUE_FOR_TYPE
 SELECT GEOMETRYCOLLECTION((SELECT @@OLD));
 
+select astext(0x0100000000030000000100000000000010);
 
 --echo End of 5.1 tests
diff --git a/sql/spatial.cc b/sql/spatial.cc
index eec028e..94d0238 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -556,7 +556,7 @@ bool Gis_line_string::get_data_as_wkt(String *txt, const char **end) const
   n_points= uint4korr(data);
   data += 4;
 
-  if (n_points < 1 ||
+  if (n_points < 1 || n_points > max_n_points ||
       no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points) ||
       txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points))
     return 1;
@@ -594,7 +594,8 @@ int Gis_line_string::geom_length(double *len) const
     return 1;
   n_points= uint4korr(data);
   data+= 4;
-  if (n_points < 1 || no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points))
+  if (n_points < 1 || n_points > max_n_points ||
+      no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points))
     return 1;
 
   get_point(&prev_x, &prev_y, data);
@@ -628,7 +629,7 @@ int Gis_line_string::is_closed(int *closed) const
     return 0;
   }
   data+= 4;
-  if (n_points == 0 ||
+  if (n_points == 0 || n_points > max_n_points ||
       no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points))
     return 1;
 
@@ -798,7 +799,8 @@ bool Gis_polygon::get_data_as_wkt(String *txt, const char **end) const
       return 1;
     n_points= uint4korr(data);
     data+= 4;
-    if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points) ||
+    if (n_points > max_n_points ||
+        no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points) ||
 	txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
       return 1;
     txt->qs_append('(');
@@ -852,7 +854,8 @@ int Gis_polygon::area(double *ar, const char **end_of_data) const
     if (no_data(data, 4))
       return 1;
     n_points= uint4korr(data);
-    if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points))
+    if (n_points > max_n_points ||
+        no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points))
       return 1;
     get_point(&prev_x, &prev_y, data+4);
     data+= (4+SIZEOF_STORED_DOUBLE*2);
@@ -888,7 +891,8 @@ int Gis_polygon::exterior_ring(String *result) const
   n_points= uint4korr(data);
   data+= 4;
   length= n_points * POINT_DATA_SIZE;
-  if (no_data(data, length) || result->reserve(1+4+4+ length))
+  if (n_points > max_n_points ||
+      no_data(data, length) || result->reserve(1+4+4+ length))
     return 1;
 
   result->q_append((char) wkb_ndr);
@@ -973,7 +977,8 @@ int Gis_polygon::centroid_xy(double *x, double *y) const
       return 1;
     org_n_points= n_points= uint4korr(data);
     data+= 4;
-    if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points))
+    if (n_points > max_n_points ||
+        no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points))
       return 1;
     get_point(&prev_x, &prev_y, data);
     data+= (SIZEOF_STORED_DOUBLE*2);
@@ -1260,7 +1265,8 @@ bool Gis_multi_line_string::get_data_as_wkt(String *txt,
       return 1;
     n_points= uint4korr(data + WKB_HEADER_SIZE);
     data+= WKB_HEADER_SIZE + 4;
-    if (no_data(data, n_points * (SIZEOF_STORED_DOUBLE*2)) ||
+    if (n_points > max_n_points ||
+        no_data(data, n_points * (SIZEOF_STORED_DOUBLE*2)) ||
 	txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
       return 1;
     txt->qs_append('(');
@@ -1521,7 +1527,8 @@ bool Gis_multi_polygon::get_data_as_wkt(String *txt, const char **end) const
         return 1;
       uint32 n_points= uint4korr(data);
       data+= 4;
-      if (no_data(data, (SIZEOF_STORED_DOUBLE * 2) * n_points) ||
+      if (n_points > max_n_points ||
+          no_data(data, (SIZEOF_STORED_DOUBLE * 2) * n_points) ||
 	  txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points,
 		       512))
 	return 1;
@@ -1604,6 +1611,8 @@ int Gis_multi_polygon::geometry_n(uint32 num, String *result) const
       if (no_data(data, 4))
 	return 1;
       n_points= uint4korr(data);
+      if (n_points > max_n_points)
+        return 1;
       data+= 4 + POINT_DATA_SIZE * n_points;
     }
   } while (--num);
diff --git a/sql/spatial.h b/sql/spatial.h
index 20b3856..7d25425 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -197,6 +197,11 @@ struct MBR
 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 */) /
+    POINT_DATA_SIZE;
+public:
   Geometry() {}                               /* Remove gcc warning */
   virtual ~Geometry() {}                        /* Remove gcc warning */
   static void *operator new(size_t size, void *buffer)
@@ -379,10 +384,6 @@ class Gis_point: public Geometry
 
 class Gis_line_string: public Geometry
 {
-  // Maximum number of points in LineString that can fit into String
-  static const uint32 max_n_points=
-    (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) /
-    POINT_DATA_SIZE;
 public:
   Gis_line_string() {}                        /* Remove gcc warning */
   virtual ~Gis_line_string() {}               /* Remove gcc warning */
-- 
1.8.1.6