diff options
author | Georgi Kodinov <georgi.kodinov@oracle.com> | 2013-03-27 16:06:33 +0200 |
---|---|---|
committer | Georgi Kodinov <georgi.kodinov@oracle.com> | 2013-03-27 16:06:33 +0200 |
commit | 0cbb7ddcd63b20783387ca85fbfa5adcc7d4437b (patch) | |
tree | a1b4fdf9d988d6240c304f73adae2f3c1ad1ace3 /sql | |
parent | 53cebed3b6188c0ce85335b4c2229d82c5e8bea5 (diff) | |
parent | e7c48834ff1827df1a35e542d1682ec55f3fe46d (diff) | |
download | mariadb-git-0cbb7ddcd63b20783387ca85fbfa5adcc7d4437b.tar.gz |
merge 5.1->5.5
Diffstat (limited to 'sql')
-rw-r--r-- | sql/spatial.cc | 53 | ||||
-rw-r--r-- | sql/spatial.h | 29 |
2 files changed, 59 insertions, 23 deletions
diff --git a/sql/spatial.cc b/sql/spatial.cc index 3b98ff2a1b6..1ee7912837e 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -377,13 +377,19 @@ 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; - if (no_data(data, (SIZEOF_STORED_DOUBLE * 2 + offset) * points)) + /* 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) return 0; /* Calculate MBR for points */ @@ -539,7 +545,7 @@ bool Gis_line_string::get_data_as_wkt(String *txt, const char **end) const data += 4; if (n_points < 1 || - no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points) || + not_enough_points(data, n_points) || txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points)) return 1; @@ -576,7 +582,7 @@ 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 || not_enough_points(data, n_points)) return 1; get_point(&prev_x, &prev_y, data); @@ -610,8 +616,7 @@ int Gis_line_string::is_closed(int *closed) const return 0; } data+= 4; - if (n_points == 0 || - no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points)) + if (n_points == 0 || not_enough_points(data, n_points)) return 1; /* Get first point */ @@ -780,7 +785,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 (not_enough_points(data, n_points) || txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points)) return 1; txt->qs_append('('); @@ -834,7 +840,7 @@ 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 (not_enough_points(data, n_points)) return 1; get_point(&prev_x, &prev_y, data+4); data+= (4+SIZEOF_STORED_DOUBLE*2); @@ -870,7 +876,7 @@ 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 (not_enough_points(data, n_points) || result->reserve(1+4+4+ length)) return 1; result->q_append((char) wkb_ndr); @@ -916,7 +922,7 @@ int Gis_polygon::interior_ring_n(uint32 num, String *result) const n_points= uint4korr(data); points_size= n_points * POINT_DATA_SIZE; data+= 4; - if (no_data(data, points_size) || result->reserve(1+4+4+ points_size)) + if (not_enough_points(data, n_points) || result->reserve(1+4+4+ points_size)) return 1; result->q_append((char) wkb_ndr); @@ -955,7 +961,7 @@ 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 (not_enough_points(data, n_points)) return 1; get_point(&prev_x, &prev_y, data); data+= (SIZEOF_STORED_DOUBLE*2); @@ -1080,15 +1086,22 @@ 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; - if (no_data(m_data, 4)) + size_t points_available; + const char *data= m_data; + + if (no_data(data, 4)) return 1; - n_points= uint4korr(m_data); - if (no_data(m_data+4, - n_points * (SIZEOF_STORED_DOUBLE * 2 + WKB_HEADER_SIZE)) || + 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 || txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points)) return 1; - *end= append_points(txt, n_points, m_data+4, WKB_HEADER_SIZE); + *end= append_points(txt, n_points, data, WKB_HEADER_SIZE); txt->length(txt->length()-1); // Remove end ',' return 0; } @@ -1242,7 +1255,7 @@ 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 (not_enough_points(data, n_points) || txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points)) return 1; txt->qs_append('('); @@ -1302,8 +1315,8 @@ int Gis_multi_line_string::geometry_n(uint32 num, String *result) const if (no_data(data, WKB_HEADER_SIZE + 4)) return 1; n_points= uint4korr(data + WKB_HEADER_SIZE); - length= WKB_HEADER_SIZE + 4+ POINT_DATA_SIZE * n_points; - if (no_data(data, length)) + length= WKB_HEADER_SIZE + 4 + POINT_DATA_SIZE * n_points; + if (not_enough_points(data + WKB_HEADER_SIZE + 4, n_points)) return 1; if (!--num) break; @@ -1503,7 +1516,7 @@ 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 (not_enough_points(data, n_points) || txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points, 512)) return 1; diff --git a/sql/spatial.h b/sql/spatial.h index 1e2decd6ef3..557bf6f4a5c 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,7 +25,7 @@ class Gis_read_stream; const uint SRID_SIZE= 4; const uint SIZEOF_STORED_DOUBLE= 8; -const uint POINT_DATA_SIZE= SIZEOF_STORED_DOUBLE*2; +const uint POINT_DATA_SIZE= (SIZEOF_STORED_DOUBLE * 2); const uint WKB_HEADER_SIZE= 1+4; const uint32 GET_SIZE_ERROR= ((uint32) -1); @@ -321,10 +321,33 @@ protected: const char *get_mbr_for_points(MBR *mbr, const char *data, uint offset) const; - inline bool no_data(const char *cur_data, uint32 data_amount) const + /** + Check if there're enough data remaining as requested + + @arg cur_data pointer to the position in the binary form + @arg data_amount number of points expected + @return true if not enough data + */ + inline bool no_data(const char *cur_data, size_t data_amount) const { return (cur_data + data_amount > m_data_end); } + + /** + Check if there're enough points remaining as requested + + 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 + @return true if there are not enough points + */ + inline bool not_enough_points(const char *data, uint32 expected_points) const + { + return (m_data_end < data || + (expected_points > ((m_data_end - data) / POINT_DATA_SIZE))); + } const char *m_data; const char *m_data_end; }; |