Opened 12 years ago
Closed 12 years ago
#1951 closed defect (fixed)
Crash in ST_Distance
Reported by: | realityexists | Owned by: | pramsey |
---|---|---|---|
Priority: | medium | Milestone: | PostGIS 2.1.0 |
Component: | postgis | Version: | master |
Keywords: | Cc: |
Description
When I run a particular plpgsql function that calls ST_Distance the PostgreSQL backend crashes:
Program received signal SIGSEGV, Segmentation fault. sphere_distance (s=0x9b4cea8, e=0x0) at lwgeodetic.c:758 758 double d_lon = e->lon - s->lon;
The following simplified function reproduces the crash:
CREATE OR REPLACE FUNCTION _distance_crash_repro6() RETURNS integer AS $BODY$ DECLARE line geography[]; i integer; current_line geography(LineString); current_distance float; BEGIN line := ARRAY[ 'POINT(-60.1529782532063 -3.00395030900105)'::geography, 'POINT(-60.1529985502867 -3.00511933469609)'::geography, 'POINT(-60.1529985502867 -3.00511933469609)'::geography]; FOR i IN array_lower(line, 1) .. array_upper(line, 1) - 1 LOOP current_line := ST_MakeLine(line[i]::geometry, line[i + 1]::geometry)::geography; current_distance := ST_Distance(current_line, 'POINT(-60.1529903235046 -3.00464549022075)'::geography); END LOOP; RETURN -1; END $BODY$ LANGUAGE plpgsql IMMUTABLE; SELECT _distance_crash_repro6();
I haven't been able to repro it without a function or without an array. Stack trace from the simplified repro attached.
"POSTGIS="2.1.0SVN r10181" GEOS="3.4.0dev-CAPI-1.8.0 r3703" PROJ="Rel. 4.8.0, 6 March 2012" GDAL="GDAL 1.9.0, released 2011/12/29" LIBXML="2.7.8" RASTER"
"PostgreSQL 9.1.4 on i686-pc-linux-gnu, compiled by gcc (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2, 32-bit"
(also happens on Windows 7 x64)
Attachments (1)
Change History (4)
by , 12 years ago
Attachment: | crash-proc-paths-stack.txt added |
---|
comment:1 by , 12 years ago
comment:2 by , 12 years ago
And looks like any simple version with just two duped coordinates will do. However duped coordinates in a larger line have no problems:
-- works select _st_distancetree('LINESTRING(0.1 0,0 0,0 0)'::geography, 'POINT(0.1 0.1)'::geography); -- works select _st_distancetree('LINESTRING(0 0,0 0,0 0.1)'::geography, 'POINT(0.1 0.1)'::geography); -- boom select _st_distancetree('LINESTRING(0 0,0 0)'::geography, 'POINT(0.1 0.1)'::geography);
The function has to hit the distance function twice to get the caching to kick in and thereby hit the tree. You can skip the cache by calling _ST_DistanceTree(geog, geog) directly for testing, and it goes boom: