summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/spatial.cc67
-rw-r--r--sql/spatial.h11
2 files changed, 55 insertions, 23 deletions
diff --git a/sql/spatial.cc b/sql/spatial.cc
index 74fc863a18b..ba1cbbcb85e 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -395,19 +395,13 @@ const char *Geometry::get_mbr_for_points(MBR *mbr, const char *data,
uint offset) const
{
uint32 points;
- size_t points_available;
/* read number of points */
if (no_data(data, 4))
return 0;
points= uint4korr(data);
data+= 4;
- /* can't use any of the helper functions due to the offset */
- points_available=
- data <= m_data_end ?
- (m_data_end - data) / (POINT_DATA_SIZE + offset) : 0;
-
- if (points_available < points)
+ if (not_enough_points(data, points, offset))
return 0;
/* Calculate MBR for points */
@@ -490,9 +484,16 @@ const Geometry::Class_info *Gis_point::get_class_info() const
uint32 Gis_line_string::get_data_size() const
{
+ size_t n_points;
if (no_data(m_data, 4))
return GET_SIZE_ERROR;
- return 4 + uint4korr(m_data) * POINT_DATA_SIZE;
+
+ n_points= uint4korr(m_data);
+
+ if (not_enough_points(m_data + 4, n_points))
+ return GET_SIZE_ERROR;
+
+ return 4 + n_points * POINT_DATA_SIZE;
}
@@ -705,10 +706,18 @@ uint32 Gis_polygon::get_data_size() const
while (n_linear_rings--)
{
+ size_t n_points;
if (no_data(data, 4))
return GET_SIZE_ERROR;
- data+= 4 + uint4korr(data)*POINT_DATA_SIZE;
+ n_points= uint4korr(data);
+ data+= 4;
+
+ if (not_enough_points(data, n_points))
+ return GET_SIZE_ERROR;
+
+ data+= n_points * POINT_DATA_SIZE;
}
+
return (uint32) (data - m_data);
}
@@ -1038,9 +1047,17 @@ const Geometry::Class_info *Gis_polygon::get_class_info() const
uint32 Gis_multi_point::get_data_size() const
{
+ size_t n_points;
+
if (no_data(m_data, 4))
return GET_SIZE_ERROR;
- return 4 + uint4korr(m_data)*(POINT_DATA_SIZE + WKB_HEADER_SIZE);
+
+ n_points= uint4korr(m_data);
+
+ if (not_enough_points(m_data + 4, n_points, WKB_HEADER_SIZE))
+ return GET_SIZE_ERROR;
+
+ return 4 + n_points * (POINT_DATA_SIZE + WKB_HEADER_SIZE);
}
@@ -1104,7 +1121,6 @@ uint Gis_multi_point::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo,
bool Gis_multi_point::get_data_as_wkt(String *txt, const char **end) const
{
uint32 n_points;
- size_t points_available;
const char *data= m_data;
if (no_data(data, 4))
@@ -1112,13 +1128,11 @@ bool Gis_multi_point::get_data_as_wkt(String *txt, const char **end) const
n_points= uint4korr(data);
data+= 4;
- points_available= data <= m_data_end ?
- (m_data_end - data) / (POINT_DATA_SIZE + WKB_HEADER_SIZE) : 0;
- /* can't use any of the helper functions due to WKB_HEADER_SIZE */
- if (n_points > points_available ||
+ if (not_enough_points(data, n_points, WKB_HEADER_SIZE) ||
txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1;
+
*end= append_points(txt, n_points, data, WKB_HEADER_SIZE);
txt->length(txt->length()-1); // Remove end ','
return 0;
@@ -1177,10 +1191,18 @@ uint32 Gis_multi_line_string::get_data_size() const
while (n_line_strings--)
{
+ size_t n_points;
+
if (no_data(data, WKB_HEADER_SIZE + 4))
return GET_SIZE_ERROR;
- data+= (WKB_HEADER_SIZE + 4 + uint4korr(data + WKB_HEADER_SIZE) *
- POINT_DATA_SIZE);
+
+ n_points= uint4korr(data + WKB_HEADER_SIZE);
+ data+= WKB_HEADER_SIZE + 4;
+
+ if (not_enough_points(data, n_points))
+ return GET_SIZE_ERROR;
+
+ data+= n_points * POINT_DATA_SIZE;
}
return (uint32) (data - m_data);
}
@@ -1432,9 +1454,16 @@ uint32 Gis_multi_polygon::get_data_size() const
while (n_linear_rings--)
{
+ size_t n_points;
if (no_data(data, 4))
- return GET_SIZE_ERROR;
- data+= 4 + uint4korr(data) * POINT_DATA_SIZE;
+ return GET_SIZE_ERROR;
+ n_points= uint4korr(data);
+ data+= 4;
+
+ if (not_enough_points(data, n_points))
+ return GET_SIZE_ERROR;
+
+ data+= n_points * POINT_DATA_SIZE;
}
}
return (uint32) (data - m_data);
diff --git a/sql/spatial.h b/sql/spatial.h
index 075ae0ecc89..60a34852178 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -335,14 +335,17 @@ protected:
Need to perform the calculation in logical units, since multiplication
can overflow the size data type.
- @arg data pointer to the begining of the points array
- @arg expected_points number of points expected
+ @arg data pointer to the begining of the points array
+ @arg expected_points number of points expected
+ @arg extra_point_space extra space for each point element in the array
@return true if there are not enough points
*/
- inline bool not_enough_points(const char *data, uint32 expected_points) const
+ inline bool not_enough_points(const char *data, uint32 expected_points,
+ uint32 extra_point_space = 0) const
{
return (m_data_end < data ||
- (expected_points > ((m_data_end - data) / POINT_DATA_SIZE)));
+ (expected_points > ((m_data_end - data) /
+ (POINT_DATA_SIZE + extra_point_space))));
}
const char *m_data;
const char *m_data_end;