From 511b9432637510617b04bde92c51a184c1e3aea8 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Sun, 10 Mar 2013 23:08:05 +0400 Subject: [PATCH 1/7] MDEV-4252 geometry query crashes server. The bug was found by Alyssa Milburn. If the number of points of a geometry feature read from binary representation is greater than 0x10000000, then the (uint32) (num_points * 16) will cut the higher byte, which leads to various errors. Fixed by additional check if (num_points > max_n_points). --- mysql-test/r/gis.result | 3 +++ mysql-test/t/gis.test | 1 + sql/spatial.cc | 27 ++++++++++++++++++--------- sql/spatial.h | 9 +++++---- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 8dad72fd3f8..69e73d018c7 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -1087,4 +1087,7 @@ NULL # SELECT GEOMETRYCOLLECTION((SELECT @@OLD)); ERROR 22007: Illegal non geometric '' value found during parsing +select astext(0x0100000000030000000100000000000010); +astext(0x0100000000030000000100000000000010) +NULL End of 5.1 tests diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index abda3e997bd..cc5d158f600 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -826,5 +826,6 @@ SELECT ISCLOSED(CONVERT(CONCAT(' ', 0x2), BINARY(20))); --error ER_ILLEGAL_VALUE_FOR_TYPE SELECT GEOMETRYCOLLECTION((SELECT @@OLD)); +select astext(0x0100000000030000000100000000000010); --echo End of 5.1 tests diff --git a/sql/spatial.cc b/sql/spatial.cc index eec028eaef1..94d0238993c 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -556,7 +556,7 @@ bool Gis_line_string::get_data_as_wkt(String *txt, const char **end) const n_points= uint4korr(data); data += 4; - if (n_points < 1 || + if (n_points < 1 || n_points > max_n_points || no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points) || txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points)) return 1; @@ -594,7 +594,8 @@ 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 || n_points > max_n_points || + no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points)) return 1; get_point(&prev_x, &prev_y, data); @@ -628,7 +629,7 @@ int Gis_line_string::is_closed(int *closed) const return 0; } data+= 4; - if (n_points == 0 || + if (n_points == 0 || n_points > max_n_points || no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points)) return 1; @@ -798,7 +799,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 (n_points > max_n_points || + no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points) || txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points)) return 1; txt->qs_append('('); @@ -852,7 +854,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 (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points)) + if (n_points > max_n_points || + no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points)) return 1; get_point(&prev_x, &prev_y, data+4); data+= (4+SIZEOF_STORED_DOUBLE*2); @@ -888,7 +891,8 @@ 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 (n_points > max_n_points || + no_data(data, length) || result->reserve(1+4+4+ length)) return 1; result->q_append((char) wkb_ndr); @@ -973,7 +977,8 @@ 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 (n_points > max_n_points || + no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points)) return 1; get_point(&prev_x, &prev_y, data); data+= (SIZEOF_STORED_DOUBLE*2); @@ -1260,7 +1265,8 @@ 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 (n_points > max_n_points || + no_data(data, n_points * (SIZEOF_STORED_DOUBLE*2)) || txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points)) return 1; txt->qs_append('('); @@ -1521,7 +1527,8 @@ 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 (n_points > max_n_points || + no_data(data, (SIZEOF_STORED_DOUBLE * 2) * n_points) || txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points, 512)) return 1; @@ -1604,6 +1611,8 @@ 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) + return 1; data+= 4 + POINT_DATA_SIZE * n_points; } } while (--num); diff --git a/sql/spatial.h b/sql/spatial.h index 20b3856ca9a..7d254252b3f 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -196,6 +196,11 @@ struct Geometry_buffer; class Geometry { +public: + // Maximum number of points in feature that can fit into String + static const uint32 max_n_points= + (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) / + POINT_DATA_SIZE; public: Geometry() {} /* Remove gcc warning */ virtual ~Geometry() {} /* Remove gcc warning */ @@ -379,10 +384,6 @@ public: class Gis_line_string: public Geometry { - // Maximum number of points in LineString that can fit into String - static const uint32 max_n_points= - (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) / - POINT_DATA_SIZE; public: Gis_line_string() {} /* Remove gcc warning */ virtual ~Gis_line_string() {} /* Remove gcc warning */ From a4a18e0cbbaf2a43507b3c2232fed700403ad04d Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 18 Mar 2013 10:35:03 +0100 Subject: [PATCH 2/7] MDEV-4289 Assertion `0' fails in make_sortkey with GROUP_CONCAT, MAKE_SET, GROUP BY Item_func_make_set wasn't taking into account the first argument when calculating maybe_null. sql/item_strfunc.cc: rewrite Item_func_make_set, removing separate storage of the first argument sql/item_strfunc.h: rewrite Item_func_make_set, removing separate storage of the first argument --- mysql-test/r/func_str.result | 7 ++++ mysql-test/t/func_str.test | 7 ++++ sql/item_create.cc | 3 +- sql/item_strfunc.cc | 72 ++++-------------------------------- sql/item_strfunc.h | 20 +--------- 5 files changed, 24 insertions(+), 85 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index aef452b7b50..db2c3430784 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -2646,4 +2646,11 @@ NULL SELECT LPAD('hi', DAY(FROM_UNIXTIME(-1)),'?'); LPAD('hi', DAY(FROM_UNIXTIME(-1)),'?') NULL +create table t1 (i int); +insert into t1 values (null),(8); +select group_concat( i ), make_set( i, 'a', 'b' ) field from t1 group by field; +group_concat( i ) field +NULL NULL +8 +drop table t1; End of 5.1 tests diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 9909974d3be..f49fa633925 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -1390,5 +1390,12 @@ SELECT REPEAT('1', DAY(FROM_UNIXTIME(-1))); SELECT RPAD('hi', DAY(FROM_UNIXTIME(-1)),'?'); SELECT LPAD('hi', DAY(FROM_UNIXTIME(-1)),'?'); +# +# MDEV-4289 Assertion `0' fails in make_sortkey with GROUP_CONCAT, MAKE_SET, GROUP BY +# +create table t1 (i int); +insert into t1 values (null),(8); +select group_concat( i ), make_set( i, 'a', 'b' ) field from t1 group by field; +drop table t1; --echo End of 5.1 tests diff --git a/sql/item_create.cc b/sql/item_create.cc index a5dc3eeb5ad..78b50ff01fc 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -3952,8 +3952,7 @@ Create_func_make_set::create_native(THD *thd, LEX_STRING name, return NULL; } - Item *param_1= item_list->pop(); - return new (thd->mem_root) Item_func_make_set(param_1, *item_list); + return new (thd->mem_root) Item_func_make_set(*item_list); } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 9cc77849094..ffa227834a9 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2233,37 +2233,14 @@ String *Item_func_elt::val_str(String *str) } -void Item_func_make_set::split_sum_func(THD *thd, Item **ref_pointer_array, - List &fields) -{ - item->split_sum_func2(thd, ref_pointer_array, fields, &item, TRUE); - Item_str_func::split_sum_func(thd, ref_pointer_array, fields); -} - - void Item_func_make_set::fix_length_and_dec() { - max_length=arg_count-1; - - if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV, 1)) + if (agg_arg_charsets(collation, args+1, arg_count-1, MY_COLL_ALLOW_CONV, 1)) return; - for (uint i=0 ; i < arg_count ; i++) + max_length=arg_count-2; + for (uint i=1 ; i < arg_count ; i++) max_length+=args[i]->max_length; - - used_tables_cache|= item->used_tables(); - not_null_tables_cache&= item->not_null_tables(); - const_item_cache&= item->const_item(); - with_sum_func= with_sum_func || item->with_sum_func; -} - - -void Item_func_make_set::update_used_tables() -{ - Item_func::update_used_tables(); - item->update_used_tables(); - used_tables_cache|=item->used_tables(); - const_item_cache&=item->const_item(); } @@ -2272,15 +2249,15 @@ String *Item_func_make_set::val_str(String *str) DBUG_ASSERT(fixed == 1); ulonglong bits; bool first_found=0; - Item **ptr=args; + Item **ptr=args+1; String *result=&my_empty_string; - bits=item->val_int(); - if ((null_value=item->null_value)) + bits=args[0]->val_int(); + if ((null_value=args[0]->null_value)) return NULL; - if (arg_count < 64) - bits &= ((ulonglong) 1 << arg_count)-1; + if (arg_count < 65) + bits &= ((ulonglong) 1 << (arg_count-1))-1; for (; bits; bits >>= 1, ptr++) { @@ -2320,39 +2297,6 @@ String *Item_func_make_set::val_str(String *str) } -Item *Item_func_make_set::transform(Item_transformer transformer, uchar *arg) -{ - DBUG_ASSERT(!current_thd->is_stmt_prepare()); - - Item *new_item= item->transform(transformer, arg); - if (!new_item) - return 0; - - /* - THD::change_item_tree() should be called only if the tree was - really transformed, i.e. when a new item has been created. - Otherwise we'll be allocating a lot of unnecessary memory for - change records at each execution. - */ - if (item != new_item) - current_thd->change_item_tree(&item, new_item); - return Item_str_func::transform(transformer, arg); -} - - -void Item_func_make_set::print(String *str, enum_query_type query_type) -{ - str->append(STRING_WITH_LEN("make_set(")); - item->print(str, query_type); - if (arg_count) - { - str->append(','); - print_args(str, 0, query_type); - } - str->append(')'); -} - - String *Item_func_char::val_str(String *str) { DBUG_ASSERT(fixed == 1); diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index e8fa041af4f..a4fae7c69a1 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -497,31 +497,13 @@ public: class Item_func_make_set :public Item_str_func { - Item *item; String tmp_str; public: - Item_func_make_set(Item *a,List &list) :Item_str_func(list),item(a) {} + Item_func_make_set(List &list) :Item_str_func(list) {} String *val_str(String *str); - bool fix_fields(THD *thd, Item **ref) - { - DBUG_ASSERT(fixed == 0); - return ((!item->fixed && item->fix_fields(thd, &item)) || - item->check_cols(1) || - Item_func::fix_fields(thd, ref)); - } - void split_sum_func(THD *thd, Item **ref_pointer_array, List &fields); void fix_length_and_dec(); - void update_used_tables(); const char *func_name() const { return "make_set"; } - - bool walk(Item_processor processor, bool walk_subquery, uchar *arg) - { - return item->walk(processor, walk_subquery, arg) || - Item_str_func::walk(processor, walk_subquery, arg); - } - Item *transform(Item_transformer transformer, uchar *arg); - virtual void print(String *str, enum_query_type query_type); }; From 589247ae86b25eaa9bd75e4f26ecd06831469311 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Mon, 18 Mar 2013 17:58:00 +0400 Subject: [PATCH 3/7] MDEV-4252 geometry query crashes server. Additional fixes for possible overflows in length-related calculations in 'spatial' implementations. Checks added to the ::get_data_size() methods. max_n_points decreased to occupy less 2G size. An object of that size is practically inoperable anyway. --- mysql-test/r/gis.result | 12 ++++++++ mysql-test/t/gis.test | 6 ++++ sql/spatial.cc | 67 +++++++++++++++++++++++++++++------------ sql/spatial.h | 2 +- 4 files changed, 66 insertions(+), 21 deletions(-) diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 69e73d018c7..7566f0beb8c 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -1087,7 +1087,19 @@ NULL # SELECT GEOMETRYCOLLECTION((SELECT @@OLD)); ERROR 22007: Illegal non geometric '' value found during parsing +# +# MDEV-4252 geometry query crashes server +# select astext(0x0100000000030000000100000000000010); astext(0x0100000000030000000100000000000010) NULL +select envelope(0x0100000000030000000100000000000010); +envelope(0x0100000000030000000100000000000010) +NULL +select geometryn(0x0100000000070000000100000001030000000200000000000000ffff0000, 1); +geometryn(0x0100000000070000000100000001030000000200000000000000ffff0000, 1) +NULL +select geometryn(0x0100000000070000000100000001030000000200000000000000ffffff0f, 1); +geometryn(0x0100000000070000000100000001030000000200000000000000ffffff0f, 1) +NULL End of 5.1 tests diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index cc5d158f600..c42541e82b8 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -826,6 +826,12 @@ SELECT ISCLOSED(CONVERT(CONCAT(' ', 0x2), BINARY(20))); --error ER_ILLEGAL_VALUE_FOR_TYPE SELECT GEOMETRYCOLLECTION((SELECT @@OLD)); +--echo # +--echo # MDEV-4252 geometry query crashes server +--echo # select astext(0x0100000000030000000100000000000010); +select envelope(0x0100000000030000000100000000000010); +select geometryn(0x0100000000070000000100000001030000000200000000000000ffff0000, 1); +select geometryn(0x0100000000070000000100000001030000000200000000000000ffffff0f, 1); --echo End of 5.1 tests diff --git a/sql/spatial.cc b/sql/spatial.cc index 94d0238993c..5a4b768140c 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -394,18 +394,19 @@ 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 points; + uint32 n_points; /* read number of points */ if (no_data(data, 4)) return 0; - points= uint4korr(data); + n_points= uint4korr(data); data+= 4; - if (no_data(data, (SIZEOF_STORED_DOUBLE * 2 + offset) * points)) + if (n_points > max_n_points || + no_data(data, (POINT_DATA_SIZE + offset) * n_points)) return 0; /* Calculate MBR for points */ - while (points--) + while (n_points--) { data+= offset; mbr->add_xy(data, data + SIZEOF_STORED_DOUBLE); @@ -484,9 +485,12 @@ const Geometry::Class_info *Gis_point::get_class_info() const uint32 Gis_line_string::get_data_size() const { - if (no_data(m_data, 4)) + 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))) return GET_SIZE_ERROR; - return 4 + uint4korr(m_data) * POINT_DATA_SIZE; + return size; } @@ -665,6 +669,9 @@ 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)) + return 1; return create_point(result, m_data + 4 + (n_points - 1) * POINT_DATA_SIZE); } @@ -674,11 +681,14 @@ int Gis_line_string::point_n(uint32 num, String *result) const uint32 n_points; if (no_data(m_data, 4)) return 1; + num--; n_points= uint4korr(m_data); - if ((uint32) (num - 1) >= n_points) // means (num > n_points || num < 1) + if (num >= n_points || + num > max_n_points || // means (num > n_points || num < 1) + no_data(m_data, num * POINT_DATA_SIZE)) return 1; - return create_point(result, m_data + 4 + (num - 1) * POINT_DATA_SIZE); + return create_point(result, m_data + 4 + num*POINT_DATA_SIZE); } const Geometry::Class_info *Gis_line_string::get_class_info() const @@ -692,6 +702,7 @@ const Geometry::Class_info *Gis_line_string::get_class_info() const uint32 Gis_polygon::get_data_size() const { uint32 n_linear_rings; + uint32 n_points; const char *data= m_data; if (no_data(data, 4)) @@ -701,10 +712,13 @@ uint32 Gis_polygon::get_data_size() const while (n_linear_rings--) { - if (no_data(data, 4)) + if (no_data(data, 4) || + (n_points= uint4korr(data)) > max_n_points) return GET_SIZE_ERROR; - data+= 4 + uint4korr(data)*POINT_DATA_SIZE; + data+= 4 + n_points*POINT_DATA_SIZE; } + if (no_data(data, 0)) + return GET_SIZE_ERROR; return (uint32) (data - m_data); } @@ -1037,9 +1051,14 @@ const Geometry::Class_info *Gis_polygon::get_class_info() const uint32 Gis_multi_point::get_data_size() const { - if (no_data(m_data, 4)) - return GET_SIZE_ERROR; - return 4 + uint4korr(m_data)*(POINT_DATA_SIZE + WKB_HEADER_SIZE); + 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)))) + return GET_SIZE_ERROR; + return size; } @@ -1107,7 +1126,8 @@ bool Gis_multi_point::get_data_as_wkt(String *txt, const char **end) const return 1; n_points= uint4korr(m_data); - if (no_data(m_data+4, + if (n_points > max_n_points || + no_data(m_data+4, n_points * (SIZEOF_STORED_DOUBLE * 2 + WKB_HEADER_SIZE)) || txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points)) return 1; @@ -1160,6 +1180,7 @@ const Geometry::Class_info *Gis_multi_point::get_class_info() const uint32 Gis_multi_line_string::get_data_size() const { uint32 n_line_strings; + uint32 n_points; const char *data= m_data; if (no_data(data, 4)) @@ -1169,11 +1190,13 @@ uint32 Gis_multi_line_string::get_data_size() const while (n_line_strings--) { - if (no_data(data, WKB_HEADER_SIZE + 4)) + if (no_data(data, WKB_HEADER_SIZE + 4) || + (n_points= uint4korr(data + WKB_HEADER_SIZE)) > max_n_points) return GET_SIZE_ERROR; - data+= (WKB_HEADER_SIZE + 4 + uint4korr(data + WKB_HEADER_SIZE) * - POINT_DATA_SIZE); + data+= (WKB_HEADER_SIZE + 4 + n_points*POINT_DATA_SIZE); } + if (no_data(data, 0)) + return GET_SIZE_ERROR; return (uint32) (data - m_data); } @@ -1327,7 +1350,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 (no_data(data, length)) + if (n_points > max_n_points || no_data(data, length)) return 1; if (!--num) break; @@ -1407,6 +1430,7 @@ const Geometry::Class_info *Gis_multi_line_string::get_class_info() const uint32 Gis_multi_polygon::get_data_size() const { uint32 n_polygons; + uint32 n_points; const char *data= m_data; if (no_data(data, 4)) @@ -1425,11 +1449,14 @@ uint32 Gis_multi_polygon::get_data_size() const while (n_linear_rings--) { - if (no_data(data, 4)) + if (no_data(data, 4) || + (n_points= uint4korr(data)) > max_n_points) return GET_SIZE_ERROR; - data+= 4 + uint4korr(data) * POINT_DATA_SIZE; + data+= 4 + n_points * POINT_DATA_SIZE; } } + if (no_data(data, 0)) + return GET_SIZE_ERROR; return (uint32) (data - m_data); } diff --git a/sql/spatial.h b/sql/spatial.h index 7d254252b3f..d7632c11143 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -199,7 +199,7 @@ class Geometry public: // Maximum number of points in feature that can fit into String static const uint32 max_n_points= - (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) / + (uint32) (INT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) / POINT_DATA_SIZE; public: Geometry() {} /* Remove gcc warning */ From 2cd7cf8fe6fa41fca124c9239468fc22f8df9957 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 18 Mar 2013 15:07:52 +0200 Subject: [PATCH 4/7] MDEV-4269 fix. Item_default_value inherited form Item_field so should create temporary table field similary. --- mysql-test/r/func_group_innodb.result | 14 ++++++++++++++ mysql-test/t/func_group_innodb.test | 14 ++++++++++++++ sql/sql_select.cc | 1 + 3 files changed, 29 insertions(+) diff --git a/mysql-test/r/func_group_innodb.result b/mysql-test/r/func_group_innodb.result index e68242a8191..9d64b63f8f0 100644 --- a/mysql-test/r/func_group_innodb.result +++ b/mysql-test/r/func_group_innodb.result @@ -185,3 +185,17 @@ member_id_to COUNT(*) 518491 5 DROP TABLE t1; # End of test BUG#12713907 +# +# MDEV-4269: crash when grouping by values() +# +SELECT @@storage_engine INTO @old_engine; +set storage_engine=innodb; +create table y select 1 b; +select 1 from y group by b; +1 +1 +select 1 from y group by values(b); +1 +1 +drop table y; +SET storage_engine=@old_engine; diff --git a/mysql-test/t/func_group_innodb.test b/mysql-test/t/func_group_innodb.test index 58f365bb244..accd1f6a6b5 100644 --- a/mysql-test/t/func_group_innodb.test +++ b/mysql-test/t/func_group_innodb.test @@ -127,3 +127,17 @@ SELECT member_id_to, COUNT(*) FROM t1 WHERE r_date = DROP TABLE t1; --echo # End of test BUG#12713907 + +--echo # +--echo # MDEV-4269: crash when grouping by values() +--echo # + +SELECT @@storage_engine INTO @old_engine; +set storage_engine=innodb; + +create table y select 1 b; +select 1 from y group by b; +select 1 from y group by values(b); +drop table y; +SET storage_engine=@old_engine; + diff --git a/sql/sql_select.cc b/sql/sql_select.cc index bc8b7a9e815..24ca1ab0174 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -9922,6 +9922,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, } case Item::FIELD_ITEM: case Item::DEFAULT_VALUE_ITEM: + case Item::INSERT_VALUE_ITEM: { Item_field *field= (Item_field*) item; bool orig_modify= modify_item; From 15a7335d77d056e860a9fdc844343c840e310e68 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Tue, 19 Mar 2013 17:16:10 +0400 Subject: [PATCH 5/7] MDEV-4296 Assertion `n_linear_rings > 0' fails in Gis_polygon::centroid_xy. Forgotten DBUG_ASSERT should be replaced with the 'return error'. --- mysql-test/r/gis.result | 6 ++++++ mysql-test/t/gis.test | 5 +++++ sql/spatial.cc | 6 ++---- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 7566f0beb8c..6ea977d5bfd 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -1102,4 +1102,10 @@ NULL select geometryn(0x0100000000070000000100000001030000000200000000000000ffffff0f, 1); geometryn(0x0100000000070000000100000001030000000200000000000000ffffff0f, 1) NULL +# +# MDEV-4296 Assertion `n_linear_rings > 0' fails in Gis_polygon::centroid_xy +# +SELECT Centroid( AsBinary( LineString(Point(0,0), Point(0,0), Point(0,0) ))); +Centroid( AsBinary( LineString(Point(0,0), Point(0,0), Point(0,0) ))) +NULL End of 5.1 tests diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index c42541e82b8..b8cce077e3e 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -834,4 +834,9 @@ select envelope(0x0100000000030000000100000000000010); select geometryn(0x0100000000070000000100000001030000000200000000000000ffff0000, 1); select geometryn(0x0100000000070000000100000001030000000200000000000000ffffff0f, 1); +--echo # +--echo # MDEV-4296 Assertion `n_linear_rings > 0' fails in Gis_polygon::centroid_xy +--echo # + +SELECT Centroid( AsBinary( LineString(Point(0,0), Point(0,0), Point(0,0) ))); --echo End of 5.1 tests diff --git a/sql/spatial.cc b/sql/spatial.cc index 5a4b768140c..afaa67763e8 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -972,13 +972,11 @@ int Gis_polygon::centroid_xy(double *x, double *y) const const char *data= m_data; bool first_loop= 1; - if (no_data(data, 4)) + if (no_data(data, 4) || + (n_linear_rings= uint4korr(data)) == 0) return 1; - n_linear_rings= uint4korr(data); data+= 4; - DBUG_ASSERT(n_linear_rings > 0); - while (n_linear_rings--) { uint32 n_points, org_n_points; From ef737284b416292d21837d7dedbffe66a4b4b8d4 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Tue, 19 Mar 2013 17:25:58 +0400 Subject: [PATCH 6/7] MDEV-4295 Server crashes in get_point on a query with Area, AsBinary, MultiPoint. Need to check if the number of points is 0 for the polygon. --- mysql-test/r/gis.result | 6 ++++++ mysql-test/t/gis.test | 5 +++++ sql/spatial.cc | 4 ++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 6ea977d5bfd..b6521636685 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -1108,4 +1108,10 @@ NULL SELECT Centroid( AsBinary( LineString(Point(0,0), Point(0,0), Point(0,0) ))); Centroid( AsBinary( LineString(Point(0,0), Point(0,0), Point(0,0) ))) NULL +# +# MDEV-4295 Server crashes in get_point on a query with Area, AsBinary, MultiPoint +# +SELECT Area(AsBinary(MultiPoint(Point(0,9), Point(0,1), Point(2,2)))); +Area(AsBinary(MultiPoint(Point(0,9), Point(0,1), Point(2,2)))) +NULL End of 5.1 tests diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index b8cce077e3e..698b9455da3 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -839,4 +839,9 @@ select geometryn(0x0100000000070000000100000001030000000200000000000000ffffff0f, --echo # SELECT Centroid( AsBinary( LineString(Point(0,0), Point(0,0), Point(0,0) ))); + +--echo # +--echo # MDEV-4295 Server crashes in get_point on a query with Area, AsBinary, MultiPoint +--echo # +SELECT Area(AsBinary(MultiPoint(Point(0,9), Point(0,1), Point(2,2)))); --echo End of 5.1 tests diff --git a/sql/spatial.cc b/sql/spatial.cc index afaa67763e8..52110960f96 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -868,7 +868,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 (n_points > max_n_points || + if (n_points == 0 || n_points > max_n_points || no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points)) return 1; get_point(&prev_x, &prev_y, data+4); @@ -989,7 +989,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 > max_n_points || + if (n_points == 0 || n_points > max_n_points || no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points)) return 1; get_point(&prev_x, &prev_y, data); From e70ce465b7f4daf7124f442c95425ad66b92b527 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 20 Mar 2013 21:20:51 +0100 Subject: [PATCH 7/7] add 'plugins' suite - empty, but the line ./mtr --suite=main,plugins will work on all branches.