diff options
author | Georgi Kodinov <georgi.kodinov@oracle.com> | 2013-03-28 17:37:29 +0200 |
---|---|---|
committer | Georgi Kodinov <georgi.kodinov@oracle.com> | 2013-03-28 17:37:29 +0200 |
commit | e927bda69f5213725c95615641db1bf511a9fcab (patch) | |
tree | fa5c5e27d5beb3164d49f89052837a35f45f8585 /sql/spatial.cc | |
parent | e85c90b9d51f58b65809fb4d8224b898d2a3ebb8 (diff) | |
download | mariadb-git-e927bda69f5213725c95615641db1bf511a9fcab.tar.gz |
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.
Diffstat (limited to 'sql/spatial.cc')
-rw-r--r-- | sql/spatial.cc | 67 |
1 files changed, 48 insertions, 19 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); |