From 0e6c889c83bcf6c37526e3a3fee192bb59cab92e Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Mon, 4 Jul 2011 16:03:36 +0500 Subject: bug #801199 Infinite recursion in Gcalc_function::count_internal with ST_BUFFER over MULTIPOINT Collections were treated mistakenly, so the counter for the final UNION operation received the wrong value. As a fix we implement Item_func_buffer::Transporter::start_collection() method, where we set the proper operation and the operand counter. start_poly() and start_line() were also modified to function correctly for the polygon as a part of a collection. per-file comments: mysql-test/r/gis-precise.result bug #801199 Infinite recursion in Gcalc_function::count_internal with ST_BUFFER over MULTIPOINT test result updated. mysql-test/t/gis-precise.test bug #801199 Infinite recursion in Gcalc_function::count_internal with ST_BUFFER over MULTIPOINT test case added. sql/item_geofunc.cc bug #801199 Infinite recursion in Gcalc_function::count_internal with ST_BUFFER over MULTIPOINT start_collection() implemented. sql/item_geofunc.h bug #801199 Infinite recursion in Gcalc_function::count_internal with ST_BUFFER over MULTIPOINT Item_func_buffer::Transporter::start_collection() defined. --- sql/item_geofunc.cc | 60 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 13 deletions(-) (limited to 'sql/item_geofunc.cc') diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index f65df790dfb..8cae6dd6564 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -1284,6 +1284,18 @@ int Item_func_buffer::Transporter::add_point_buffer(double x, double y) int Item_func_buffer::Transporter::start_line() { + if (buffer_op == Gcalc_function::op_difference) + { + skip_line= TRUE; + return 0; + } + + m_nshapes= 0; + + if (m_fn->reserve_op_buffer(2)) + return 1; + last_shape_pos= m_fn->get_next_operation_pos(); + m_fn->add_operation(buffer_op, 0); m_npoints= 0; int_start_line(); return 0; @@ -1292,11 +1304,25 @@ int Item_func_buffer::Transporter::start_line() int Item_func_buffer::Transporter::start_poly() { - ++m_nshapes; + m_nshapes= 1; + + if (m_fn->reserve_op_buffer(2)) + return 1; + last_shape_pos= m_fn->get_next_operation_pos(); + m_fn->add_operation(buffer_op, 0); return Gcalc_operation_transporter::start_poly(); } +int Item_func_buffer::Transporter::complete_poly() +{ + if (Gcalc_operation_transporter::complete_poly()) + return 1; + m_fn->add_operands_to_op(last_shape_pos, m_nshapes); + return 0; +} + + int Item_func_buffer::Transporter::start_ring() { m_npoints= 0; @@ -1304,8 +1330,20 @@ int Item_func_buffer::Transporter::start_ring() } +int Item_func_buffer::Transporter::start_collection(int n_objects) +{ + if (m_fn->reserve_op_buffer(1)) + return 1; + m_fn->add_operation(Gcalc_function::op_union, n_objects); + return 0; +} + + int Item_func_buffer::Transporter::add_point(double x, double y) { + if (skip_line) + return 0; + if (m_npoints && x == x2 && y == y2) return 0; @@ -1374,9 +1412,14 @@ int Item_func_buffer::Transporter::complete() int Item_func_buffer::Transporter::complete_line() { - if (complete()) - return 1; - int_complete_line(); + if (!skip_line) + { + if (complete()) + return 1; + int_complete_line(); + m_fn->add_operands_to_op(last_shape_pos, m_nshapes); + } + skip_line= FALSE; return 0; } @@ -1396,7 +1439,6 @@ String *Item_func_buffer::val_str(String *str_value) double dist= args[1]->val_real(); Geometry_buffer buffer; Geometry *g; - uint32 union_pos; uint32 srid= 0; String *str_result= NULL; Transporter trn(&func, &collector, dist); @@ -1418,17 +1460,9 @@ String *Item_func_buffer::val_str(String *str_value) goto mem_error; } - if (func.reserve_op_buffer(2)) - goto mem_error; - /* will specify operands later */ - union_pos= func.get_next_operation_pos(); - func.add_operation((dist > 0.0) ? Gcalc_function::op_union : - Gcalc_function::op_difference, 0); - if (g->store_shapes(&trn)) goto mem_error; - func.add_operands_to_op(union_pos, trn.m_nshapes); collector.prepare_operation(); if (func.alloc_states()) goto mem_error; -- cgit v1.2.1