diff options
author | Alexey Botchkov <holyfoot@askmonty.org> | 2011-07-05 19:42:35 +0500 |
---|---|---|
committer | Alexey Botchkov <holyfoot@askmonty.org> | 2011-07-05 19:42:35 +0500 |
commit | b30bf2f6fbfeb0bcfda34fb2d2cdb5f322a5f815 (patch) | |
tree | 8a211b1bb2d3b9502b2bb05309285832c6a9d8a8 /sql/gcalc_tools.cc | |
parent | 9ac141c4a59bfe0b4b01926dba530618d95a2dec (diff) | |
download | mariadb-git-b30bf2f6fbfeb0bcfda34fb2d2cdb5f322a5f815.tar.gz |
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.
Diffstat (limited to 'sql/gcalc_tools.cc')
-rw-r--r-- | sql/gcalc_tools.cc | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/sql/gcalc_tools.cc b/sql/gcalc_tools.cc index 0e2970116ce..11d452cd8cf 100644 --- a/sql/gcalc_tools.cc +++ b/sql/gcalc_tools.cc @@ -419,17 +419,16 @@ int Gcalc_result_receiver::get_result_typeid() int Gcalc_result_receiver::move_hole(uint32 dest_position, uint32 source_position, - uint32 *new_dest_position) + uint32 *position_shift) { char *ptr; int source_len; + + *position_shift= source_len= buffer.length() - source_position; + if (dest_position == source_position) - { - *new_dest_position= position(); return 0; - } - source_len= buffer.length() - source_position; if (buffer.reserve(source_len, MY_ALIGN(source_len, 512))) return 1; @@ -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, buffer.length() - dest_position); memcpy(ptr + dest_position, ptr + buffer.length(), source_len); - *new_dest_position= dest_position + source_len; return 0; } @@ -1098,6 +1096,8 @@ int Gcalc_operation_reducer::get_line_result(res_point *cur, int Gcalc_operation_reducer::get_result(Gcalc_result_receiver *storage) { + poly_instance *polygons= NULL; + *m_res_hook= NULL; while (m_result) { @@ -1112,19 +1112,28 @@ int Gcalc_operation_reducer::get_result(Gcalc_result_receiver *storage) { if (m_result->outer_poly) { - uint32 *insert_position, hole_position; - insert_position= &m_result->outer_poly->first_poly_node->poly_position; - DBUG_ASSERT(*insert_position); + uint32 insert_position, hole_position, position_shift; + poly_instance *cur_poly; + insert_position= m_result->outer_poly->first_poly_node->poly_position; + DBUG_ASSERT(insert_position); hole_position= storage->position(); storage->start_shape(Gcalc_function::shape_hole); if (get_polygon_result(m_result, storage) || - storage->move_hole(*insert_position, hole_position, - insert_position)) + storage->move_hole(insert_position, hole_position, + &position_shift)) 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 { 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); if (get_polygon_result(m_result, storage)) return 1; |