Commit e927bda6 authored by Georgi Kodinov's avatar Georgi Kodinov

Addendum #1 to the fix for bug #16451878 : GEOMETRY QUERY CRASHES SERVER

Fixed the get_data_size() methods for multi-point features to check properly for end 
of their respective data arrays.
Extended the point checking function to take a 3d optional argument so cases where
there's additional data in each array element (besides the point data itself) can be
covered by the helper function.
Fixed the 3 cases where such offset was present to use the proper checking helper 
function.
Test cases added.
Fixed review comments.
parent e85c90b9
......@@ -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);
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment