diff options
author | Igor Babaev <igor@askmonty.org> | 2013-08-15 14:04:20 -0700 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2013-08-15 14:04:20 -0700 |
commit | 960720b10dc463a73214786302f009356c2284ce (patch) | |
tree | e9c7748d0625f14a4c3a2a1d328b2ff0cace1990 /sql | |
parent | f1b4718ec894664df221704bb70fed80bdc14070 (diff) | |
parent | 7ba78277b4d76649501e85f05be2780e00ffc9c3 (diff) | |
download | mariadb-git-960720b10dc463a73214786302f009356c2284ce.tar.gz |
Merge 5.2->5.3
Diffstat (limited to 'sql')
-rw-r--r-- | sql/spatial.cc | 84 | ||||
-rw-r--r-- | sql/spatial.h | 24 | ||||
-rw-r--r-- | sql/sql_select.cc | 11 | ||||
-rw-r--r-- | sql/table.cc | 16 |
4 files changed, 74 insertions, 61 deletions
diff --git a/sql/spatial.cc b/sql/spatial.cc index 65ba01bf44e..8f74d4fa4a7 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -443,19 +443,18 @@ const char *Geometry::append_points(String *txt, uint32 n_points, const char *Geometry::get_mbr_for_points(MBR *mbr, const char *data, uint offset) const { - uint32 n_points; + uint32 points; /* read number of points */ if (no_data(data, 4)) return 0; - n_points= uint4korr(data); + points= uint4korr(data); data+= 4; - if (n_points > max_n_points || - no_data(data, (POINT_DATA_SIZE + offset) * n_points)) + if (not_enough_points(data, points, offset)) return 0; /* Calculate MBR for points */ - while (n_points--) + while (points--) { data+= offset; mbr->add_xy(data, data + SIZEOF_STORED_DOUBLE); @@ -559,12 +558,16 @@ const Geometry::Class_info *Gis_point::get_class_info() const uint32 Gis_line_string::get_data_size() const { - uint32 n_points, size; - if (no_data(m_data, 4) || - (n_points= uint4korr(m_data)) > max_n_points || - no_data(m_data, (size= 4 + n_points * POINT_DATA_SIZE))) + uint32 n_points; + if (no_data(m_data, 4)) return GET_SIZE_ERROR; - return 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; } @@ -603,9 +606,8 @@ uint Gis_line_string::init_from_wkb(const char *wkb, uint len, const char *wkb_end; Gis_point p; - if (len < 4 || - (n_points= wkb_get_uint(wkb, bo)) < 1 || - n_points > max_n_points) + if (len < 4 || (n_points= wkb_get_uint(wkb, bo)) < 1 || + ((len - 4) / POINT_DATA_SIZE) < n_points) return 0; proper_length= 4 + n_points * POINT_DATA_SIZE; @@ -635,7 +637,7 @@ bool Gis_line_string::get_data_as_wkt(String *txt, const char **end) const data += 4; if (n_points < 1 || - no_data(data, POINT_DATA_SIZE * n_points) || + not_enough_points(data, n_points) || txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points)) return 1; @@ -672,8 +674,7 @@ int Gis_line_string::geom_length(double *len, const char **end) const return 1; n_points= uint4korr(data); data+= 4; - if (n_points < 1 || n_points > max_n_points || - no_data(data, POINT_DATA_SIZE * n_points)) + if (n_points < 1 || not_enough_points(data, n_points)) return 1; get_point(&prev_x, &prev_y, data); @@ -721,8 +722,7 @@ int Gis_line_string::is_closed(int *closed) const return 0; } data+= 4; - if (n_points == 0 || n_points > max_n_points || - no_data(data, POINT_DATA_SIZE * n_points)) + if (n_points == 0 || not_enough_points(data, n_points)) return 1; /* Get first point */ @@ -757,8 +757,7 @@ int Gis_line_string::end_point(String *result) const if (no_data(m_data, 4)) return 1; n_points= uint4korr(m_data); - if (n_points == 0 || n_points > max_n_points || - no_data(m_data, POINT_DATA_SIZE * n_points)) + if (n_points == 0 || not_enough_points(m_data+4, n_points)) return 1; return create_point(result, m_data + 4 + (n_points - 1) * POINT_DATA_SIZE); } @@ -771,9 +770,7 @@ int Gis_line_string::point_n(uint32 num, String *result) const return 1; num--; n_points= uint4korr(m_data); - if (num >= n_points || - num > max_n_points || // means (num > n_points || num < 1) - no_data(m_data, num * POINT_DATA_SIZE)) + if (num >= n_points || not_enough_points(m_data+4, n_points)) return 1; return create_point(result, m_data + 4 + num*POINT_DATA_SIZE); @@ -837,7 +834,7 @@ uint32 Gis_polygon::get_data_size() const while (n_linear_rings--) { if (no_data(data, 4) || - (n_points= uint4korr(data)) > max_n_points) + not_enough_points(data+4, n_points= uint4korr(data))) return GET_SIZE_ERROR; data+= 4 + n_points*POINT_DATA_SIZE; } @@ -981,8 +978,7 @@ bool Gis_polygon::get_data_as_wkt(String *txt, const char **end) const return 1; n_points= uint4korr(data); data+= 4; - if (n_points > max_n_points || - no_data(data, POINT_DATA_SIZE * 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('('); @@ -1036,8 +1032,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 (n_points == 0 || n_points > max_n_points || - no_data(data, POINT_DATA_SIZE * n_points)) + if (n_points == 0 || + not_enough_points(data, n_points)) return 1; get_point(&prev_x, &prev_y, data+4); data+= (4+POINT_DATA_SIZE); @@ -1073,8 +1069,7 @@ int Gis_polygon::exterior_ring(String *result) const n_points= uint4korr(data); data+= 4; length= n_points * POINT_DATA_SIZE; - if (n_points > max_n_points || - 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); @@ -1120,7 +1115,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); @@ -1157,8 +1152,7 @@ int Gis_polygon::centroid_xy(double *x, double *y) const return 1; org_n_points= n_points= uint4korr(data); data+= 4; - if (n_points == 0 || n_points > max_n_points || - no_data(data, POINT_DATA_SIZE * n_points)) + if (n_points == 0 || not_enough_points(data, n_points)) return 1; get_point(&prev_x, &prev_y, data); data+= POINT_DATA_SIZE; @@ -1286,13 +1280,12 @@ const Geometry::Class_info *Gis_polygon::get_class_info() const uint32 Gis_multi_point::get_data_size() const { uint32 n_points; - uint32 size; if (no_data(m_data, 4) || - (n_points= uint4korr(m_data)) > max_n_points || - no_data(m_data, (size= 4 + n_points*(POINT_DATA_SIZE + WKB_HEADER_SIZE)))) + not_enough_points(m_data+4, (n_points= uint4korr(m_data)), + WKB_HEADER_SIZE)) return GET_SIZE_ERROR; - return size; + return 4 + n_points * (POINT_DATA_SIZE + WKB_HEADER_SIZE); } @@ -1387,7 +1380,7 @@ bool Gis_multi_point::get_data_as_wkt(String *txt, const char **end) const n_points= uint4korr(m_data); if (n_points > max_n_points || - no_data(m_data+4, n_points * (POINT_DATA_SIZE + WKB_HEADER_SIZE)) || + not_enough_points(m_data+4, n_points, WKB_HEADER_SIZE) || 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); @@ -1479,7 +1472,8 @@ uint32 Gis_multi_line_string::get_data_size() const while (n_line_strings--) { if (no_data(data, WKB_HEADER_SIZE + 4) || - (n_points= uint4korr(data + WKB_HEADER_SIZE)) > max_n_points) + not_enough_points(data + WKB_HEADER_SIZE+4, + (n_points= uint4korr(data + WKB_HEADER_SIZE)))) return GET_SIZE_ERROR; data+= (WKB_HEADER_SIZE + 4 + n_points*POINT_DATA_SIZE); } @@ -1608,8 +1602,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 (n_points > max_n_points || - no_data(data, n_points * POINT_DATA_SIZE) || + if (not_enough_points(data, n_points) || txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points)) return 1; txt->qs_append('('); @@ -1670,7 +1663,7 @@ int Gis_multi_line_string::geometry_n(uint32 num, String *result) const return 1; n_points= uint4korr(data + WKB_HEADER_SIZE); length= WKB_HEADER_SIZE + 4+ POINT_DATA_SIZE * n_points; - if (n_points > max_n_points || no_data(data, length)) + if (not_enough_points(data+WKB_HEADER_SIZE+4, n_points)) return 1; if (!--num) break; @@ -1801,7 +1794,7 @@ uint32 Gis_multi_polygon::get_data_size() const while (n_linear_rings--) { if (no_data(data, 4) || - (n_points= uint4korr(data)) > max_n_points) + not_enough_points(data+4, (n_points= uint4korr(data)))) return GET_SIZE_ERROR; data+= 4 + n_points * POINT_DATA_SIZE; } @@ -1935,8 +1928,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 (n_points > max_n_points || - no_data(data, POINT_DATA_SIZE * n_points) || + if (not_enough_points(data, n_points) || txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points, 512)) return 1; @@ -2019,7 +2011,7 @@ 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) + if (not_enough_points(data + 4, n_points)) return 1; data+= 4 + POINT_DATA_SIZE * n_points; } diff --git a/sql/spatial.h b/sql/spatial.h index aa7e8fd0c8d..b9b9bddf5f9 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -212,11 +212,6 @@ struct Geometry_buffer; class Geometry { public: - // Maximum number of points in feature that can fit into String - static const uint32 max_n_points= - (uint32) (INT_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) @@ -337,6 +332,25 @@ protected: { 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 + @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, + uint32 extra_point_space = 0) const + { + return (m_data_end < data || + (expected_points > ((m_data_end - data) / + (POINT_DATA_SIZE + extra_point_space)))); + } const char *m_data; const char *m_data_end; }; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 40021baa954..5e594b99327 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8664,19 +8664,18 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) else { sel->needed_reg=tab->needed_reg; - sel->quick_keys.clear_all(); } + sel->quick_keys= tab->table->quick_keys; if (!sel->quick_keys.is_subset(tab->checked_keys) || !sel->needed_reg.is_subset(tab->checked_keys)) { - tab->keys=sel->quick_keys; - tab->keys.merge(sel->needed_reg); tab->use_quick= (!sel->needed_reg.is_clear_all() && - (select->quick_keys.is_clear_all() || - (select->quick && - (select->quick->records >= 100L)))) ? + (sel->quick_keys.is_clear_all() || + (sel->quick && + (sel->quick->records >= 100L)))) ? 2 : 1; sel->read_tables= used_tables & ~current_map; + sel->quick_keys.clear_all(); } if (i != join->const_tables && tab->use_quick != 2 && !tab->first_inner) diff --git a/sql/table.cc b/sql/table.cc index 7c5f9ac82cb..9e1c53f7b22 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1801,7 +1801,7 @@ bool fix_vcol_expr(THD *thd, bool result= TRUE; TABLE_LIST tables; TABLE_LIST *save_table_list, *save_first_table, *save_last_table; - int error; + int error= 0; Name_resolution_context *context; const char *save_where; char* db_name; @@ -1849,9 +1849,17 @@ bool fix_vcol_expr(THD *thd, save_use_only_table_context= thd->lex->use_only_table_context; thd->lex->use_only_table_context= TRUE; /* Fix fields referenced to by the virtual column function */ - thd->lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VCOL_EXPR; - error= func_expr->fix_fields(thd, (Item**)0); - thd->lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_VCOL_EXPR; + if (!func_expr->fixed) + { + thd->lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VCOL_EXPR; + error= func_expr->fix_fields(thd, &vcol_info->expr_item); + thd->lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_VCOL_EXPR; + } + + /* fix_fields could change the expression */ + func_expr= vcol_info->expr_item; + /* Number of columns will be checked later */ + /* Restore the original context*/ thd->lex->use_only_table_context= save_use_only_table_context; context->table_list= save_table_list; |