Commit f3b850a7 authored by Alexey Botchkov's avatar Alexey Botchkov

bug #804305 Crash in wkb_get_double with ST_INTERSECTION.

        That crash happened with the complicated topology of the result.
        If we found a hole in a polygon whose outside border was already
        found, we need to paste the hole right after it and respectively
        shift polygons after it. Also we need to update poly_position fields
        in these polygons. That last thing wasn't properly done that led to the
        crash.
        To fix that we keep the list of the found polygons and update the
        poly_positions that are bigger or equal to where we placed the next hole.


per-file comments:
  mysql-test/r/gis-precise.result
bug #804305 Crash in wkb_get_double with ST_INTERSECTION.
        test result updated.
  mysql-test/t/gis-precise.test
bug #804305 Crash in wkb_get_double with ST_INTERSECTION.
        test result added.
  sql/gcalc_tools.cc
bug #804305 Crash in wkb_get_double with ST_INTERSECTION.
        keep the list of the found polygons and update their poly_position fields respectively.
  sql/gcalc_tools.h
bug #804305 Crash in wkb_get_double with ST_INTERSECTION.
        Gcalc_result_receiver::move_hole interface changed.
parent 7f55ea12
...@@ -218,3 +218,17 @@ Round(ST_Area(ST_BUFFER(MultipointFromText('MULTIPOINT(7 7,3 7,7 2,7 4 ,7 7)'), ...@@ -218,3 +218,17 @@ Round(ST_Area(ST_BUFFER(MultipointFromText('MULTIPOINT(7 7,3 7,7 2,7 4 ,7 7)'),
SELECT ST_INTERSECTION(NULL, NULL); SELECT ST_INTERSECTION(NULL, NULL);
ST_INTERSECTION(NULL, NULL) ST_INTERSECTION(NULL, NULL)
NULL NULL
SELECT ASTEXT(ST_INTERSECTION(
MULTIPOLYGONFROMTEXT('MULTIPOLYGON(((2 2,2 8,8 8,8 2,2 2),(4 4,4 6,6 6,6 4,4 4)),
((0 5,3 5,3 0,0 0,0 1,2 1,2 2,0 2,0 5), (1 3,2 3,2 4,1 4,1 3)),
((2 2,5 2,4 4,2 8,2 2)))'),
MULTIPOLYGONFROMTEXT('MULTIPOLYGON(((3 5,2 4,2 5,3 5)),
((2 2,9 2,0 2,2 6,2 2)),
((2 2,2 8,8 8,8 2,2 2), (4 4,4 6,6 6,6 4,4 4)),
((9 9,6 8,7 0,9 9)))')));
ASTEXT(ST_INTERSECTION(
MULTIPOLYGONFROMTEXT('MULTIPOLYGON(((2 2,2 8,8 8,8 2,2 2),(4 4,4 6,6 6,6 4,4 4)),
((0 5,3 5,3 0,0 0,0 1,2 1,2 2,0 2,0 5), (1 3,2 3,2 4,1 4,1 3)),
((2 2,5 2,4 4,2 8,2 2)))'),
MULTIPOLY
MULTIPOLYGON(((2 2,3 2,2 2)),((5 2,0 2,5 2)),((2 2,0 2,1.5 5,2 5,2 2),(1 3,1 4,2 4,2 3,1 3)),((2 2,2 8,8 8,8 2,5 2,2 2),(6 4,4 4,4 6,6 6,6 4)))
...@@ -121,3 +121,12 @@ SELECT Round(ST_Area(ST_BUFFER(MultipointFromText('MULTIPOINT(7 7,3 7,7 2,7 4 ,7 ...@@ -121,3 +121,12 @@ SELECT Round(ST_Area(ST_BUFFER(MultipointFromText('MULTIPOINT(7 7,3 7,7 2,7 4 ,7
#bug 801212 Assertion with ST_INTERSECTION on NULL values #bug 801212 Assertion with ST_INTERSECTION on NULL values
SELECT ST_INTERSECTION(NULL, NULL); SELECT ST_INTERSECTION(NULL, NULL);
#bug 804305 Crash in wkb_get_double with ST_INTERSECTION
SELECT ASTEXT(ST_INTERSECTION(
MULTIPOLYGONFROMTEXT('MULTIPOLYGON(((2 2,2 8,8 8,8 2,2 2),(4 4,4 6,6 6,6 4,4 4)),
((0 5,3 5,3 0,0 0,0 1,2 1,2 2,0 2,0 5), (1 3,2 3,2 4,1 4,1 3)),
((2 2,5 2,4 4,2 8,2 2)))'),
MULTIPOLYGONFROMTEXT('MULTIPOLYGON(((3 5,2 4,2 5,3 5)),
((2 2,9 2,0 2,2 6,2 2)),
((2 2,2 8,8 8,8 2,2 2), (4 4,4 6,6 6,6 4,4 4)),
((9 9,6 8,7 0,9 9)))')));
...@@ -419,17 +419,16 @@ int Gcalc_result_receiver::get_result_typeid() ...@@ -419,17 +419,16 @@ int Gcalc_result_receiver::get_result_typeid()
int Gcalc_result_receiver::move_hole(uint32 dest_position, uint32 source_position, int Gcalc_result_receiver::move_hole(uint32 dest_position, uint32 source_position,
uint32 *new_dest_position) uint32 *position_shift)
{ {
char *ptr; char *ptr;
int source_len; int source_len;
*position_shift= source_len= buffer.length() - source_position;
if (dest_position == source_position) if (dest_position == source_position)
{
*new_dest_position= position();
return 0; return 0;
}
source_len= buffer.length() - source_position;
if (buffer.reserve(source_len, MY_ALIGN(source_len, 512))) if (buffer.reserve(source_len, MY_ALIGN(source_len, 512)))
return 1; return 1;
...@@ -437,7 +436,6 @@ int Gcalc_result_receiver::move_hole(uint32 dest_position, uint32 source_positio ...@@ -437,7 +436,6 @@ int Gcalc_result_receiver::move_hole(uint32 dest_position, uint32 source_positio
memmove(ptr + dest_position + source_len, ptr + dest_position, memmove(ptr + dest_position + source_len, ptr + dest_position,
buffer.length() - dest_position); buffer.length() - dest_position);
memcpy(ptr + dest_position, ptr + buffer.length(), source_len); memcpy(ptr + dest_position, ptr + buffer.length(), source_len);
*new_dest_position= dest_position + source_len;
return 0; return 0;
} }
...@@ -1098,6 +1096,8 @@ int Gcalc_operation_reducer::get_line_result(res_point *cur, ...@@ -1098,6 +1096,8 @@ int Gcalc_operation_reducer::get_line_result(res_point *cur,
int Gcalc_operation_reducer::get_result(Gcalc_result_receiver *storage) int Gcalc_operation_reducer::get_result(Gcalc_result_receiver *storage)
{ {
poly_instance *polygons= NULL;
*m_res_hook= NULL; *m_res_hook= NULL;
while (m_result) while (m_result)
{ {
...@@ -1112,19 +1112,28 @@ int Gcalc_operation_reducer::get_result(Gcalc_result_receiver *storage) ...@@ -1112,19 +1112,28 @@ int Gcalc_operation_reducer::get_result(Gcalc_result_receiver *storage)
{ {
if (m_result->outer_poly) if (m_result->outer_poly)
{ {
uint32 *insert_position, hole_position; uint32 insert_position, hole_position, position_shift;
insert_position= &m_result->outer_poly->first_poly_node->poly_position; poly_instance *cur_poly;
DBUG_ASSERT(*insert_position); insert_position= m_result->outer_poly->first_poly_node->poly_position;
DBUG_ASSERT(insert_position);
hole_position= storage->position(); hole_position= storage->position();
storage->start_shape(Gcalc_function::shape_hole); storage->start_shape(Gcalc_function::shape_hole);
if (get_polygon_result(m_result, storage) || if (get_polygon_result(m_result, storage) ||
storage->move_hole(*insert_position, hole_position, storage->move_hole(insert_position, hole_position,
insert_position)) &position_shift))
return 1; return 1;
for (cur_poly= polygons;
cur_poly && *cur_poly->after_poly_position >= insert_position;
cur_poly= cur_poly->get_next())
*cur_poly->after_poly_position+= position_shift;
} }
else else
{ {
uint32 *poly_position= &m_result->poly_position; uint32 *poly_position= &m_result->poly_position;
poly_instance *p= new_poly();
p->after_poly_position= poly_position;
p->next= polygons;
polygons= p;
storage->start_shape(Gcalc_function::shape_polygon); storage->start_shape(Gcalc_function::shape_polygon);
if (get_polygon_result(m_result, storage)) if (get_polygon_result(m_result, storage))
return 1; return 1;
......
...@@ -170,7 +170,7 @@ public: ...@@ -170,7 +170,7 @@ public:
int get_result_typeid(); int get_result_typeid();
uint32 position() { return buffer.length(); } uint32 position() { return buffer.length(); }
int move_hole(uint32 dest_position, uint32 source_position, int move_hole(uint32 dest_position, uint32 source_position,
uint32 *new_dest_position); uint32 *position_shift);
}; };
...@@ -233,6 +233,13 @@ public: ...@@ -233,6 +233,13 @@ public:
active_thread *get_next() { return (active_thread *)next; } active_thread *get_next() { return (active_thread *)next; }
}; };
class poly_instance : public Gcalc_dyn_list::Item
{
public:
uint32 *after_poly_position;
poly_instance *get_next() { return (poly_instance *)next; }
};
protected: protected:
Gcalc_function *m_fn; Gcalc_function *m_fn;
Gcalc_dyn_list::Item **m_res_hook; Gcalc_dyn_list::Item **m_res_hook;
...@@ -253,6 +260,8 @@ protected: ...@@ -253,6 +260,8 @@ protected:
active_thread *new_active_thread() { return (active_thread *)new_item(); } active_thread *new_active_thread() { return (active_thread *)new_item(); }
poly_instance *new_poly() { return (poly_instance *) new_item(); }
private: private:
int continue_range(active_thread *t, const Gcalc_heap::Info *p); int continue_range(active_thread *t, const Gcalc_heap::Info *p);
int continue_i_range(active_thread *t, const Gcalc_heap::Info *p, int continue_i_range(active_thread *t, const Gcalc_heap::Info *p,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment