From 91f8b43387e1474ce1697ad6be94d354ba14323c Mon Sep 17 00:00:00 2001 From: Paul Ramsey Date: Wed, 15 Aug 2012 18:55:56 +0000 Subject: [PATCH] Crash in ST_Distance (#1951) git-svn-id: http://svn.osgeo.org/postgis/trunk@10183 b70326c6-7e19-0410-871a-916f4a2858ee --- NEWS | 1 + liblwgeom/cunit/cu_tree.c | 13 +++++++++++++ liblwgeom/lwgeodetic_tree.c | 31 +++++++++++++++++++++---------- 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/NEWS b/NEWS index 6c8cf83b1..74a70cd04 100644 --- a/NEWS +++ b/NEWS @@ -44,6 +44,7 @@ PostGIS 2.1.0 when count is zero - #1932, fix raster2pgsql of syntax for index tablespaces - #1939, remove custom data types: summarystats, histogram, quantile, valuecount + - #1951, remove crash on zero-length linestrings PostGIS 2.0.1 2012/06/22 diff --git a/liblwgeom/cunit/cu_tree.c b/liblwgeom/cunit/cu_tree.c index 04c232feb..b27a82a28 100644 --- a/liblwgeom/cunit/cu_tree.c +++ b/liblwgeom/cunit/cu_tree.c @@ -183,6 +183,19 @@ static void test_tree_circ_distance(void) spheroid_init(&s, 1.0, 1.0); + /* Ticket #1951 */ + line = lwgeom_as_lwline(lwgeom_from_wkt("LINESTRING(0 0, 0 0)", LW_PARSER_CHECK_NONE)); + point = lwgeom_as_lwpoint(lwgeom_from_wkt("POINT(0.1 0.1)", LW_PARSER_CHECK_NONE)); + cline = circ_tree_new(line->points); + cpoint = circ_tree_new(point->point); + distance_tree = circ_tree_distance_tree(cpoint, cline, &s, threshold); + distance_geom = lwgeom_distance_spheroid((LWGEOM*)line, (LWGEOM*)point, &s, threshold); + circ_tree_free(cline); + circ_tree_free(cpoint); + lwline_free(line); + lwpoint_free(point); + CU_ASSERT_DOUBLE_EQUAL(distance_geom, distance_geom, 0.0001); + line = lwgeom_as_lwline(lwgeom_from_wkt("LINESTRING(-1 -1,0 -1,1 -1,1 0,1 1,0 0,-1 1,-1 0,-1 -1)", LW_PARSER_CHECK_NONE)); point = lwgeom_as_lwpoint(lwgeom_from_wkt("POINT(-2 0)", LW_PARSER_CHECK_NONE)); cline = circ_tree_new(line->points); diff --git a/liblwgeom/lwgeodetic_tree.c b/liblwgeom/lwgeodetic_tree.c index 5231cd700..8d892ceab 100644 --- a/liblwgeom/lwgeodetic_tree.c +++ b/liblwgeom/lwgeodetic_tree.c @@ -84,6 +84,22 @@ circ_node_leaf_new(const POINTARRAY* pa, int i) return node; } +/** +* Return a point node (zero radius, referencing one point) +*/ +static CIRC_NODE* +circ_node_leaf_point_new(const POINTARRAY* pa) +{ + CIRC_NODE* tree = lwalloc(sizeof(CIRC_NODE)); + tree->p1 = tree->p2 = (POINT2D*)getPoint_internal(pa, 0); + geographic_point_init(tree->p1->x, tree->p1->y, &(tree->center)); + tree->radius = 0.0; + tree->nodes = NULL; + tree->num_nodes = 0; + tree->edge_num = 0; + return tree; +} + /** * Comparing on geohash ensures that nearby nodes will be close * to each other in the list. @@ -287,16 +303,7 @@ circ_tree_new(const POINTARRAY* pa) /* Special handling for a single point */ if ( pa->npoints == 1 ) - { - tree = lwalloc(sizeof(CIRC_NODE)); - tree->p1 = tree->p2 = (POINT2D*)getPoint_internal(pa, 0); - geographic_point_init(tree->p1->x, tree->p1->y, &(tree->center)); - tree->radius = 0.0; - tree->nodes = NULL; - tree->num_nodes = 0; - tree->edge_num = 0; - return tree; - } + return circ_node_leaf_point_new(pa); /* First create a flat list of nodes, one per edge. */ num_edges = pa->npoints - 1; @@ -308,6 +315,10 @@ circ_tree_new(const POINTARRAY* pa) if ( node ) /* Not zero length? */ nodes[j++] = node; } + + /* Special case: only zero-length edges. Make a point node. */ + if ( j == 0 ) + return circ_node_leaf_point_new(pa); /* Merge the node list pairwise up into a tree */ tree = circ_nodes_merge(nodes, j); -- 2.40.0