From 8b9b187c8ecba977505859a4dfb214e5df601fab Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Wed, 14 Dec 2011 16:02:44 +0000 Subject: [PATCH] Fix crash on ST_AsGML('POLYGON EMPTY') (#681) Also tweak GML of empty types to be smaller and include regression testing both at the liblwgeom and sql level git-svn-id: http://svn.osgeo.org/postgis/trunk@8412 b70326c6-7e19-0410-871a-916f4a2858ee --- liblwgeom/cunit/cu_out_gml.c | 82 +++++++++++------- liblwgeom/lwout_gml.c | 155 ++++++++++++++++++----------------- regress/empty.sql | 25 +++--- regress/empty_expected | 24 ++++-- 4 files changed, 162 insertions(+), 124 deletions(-) diff --git a/liblwgeom/cunit/cu_out_gml.c b/liblwgeom/cunit/cu_out_gml.c index f0a5f45eb..706e01b16 100644 --- a/liblwgeom/cunit/cu_out_gml.c +++ b/liblwgeom/cunit/cu_out_gml.c @@ -208,7 +208,6 @@ static void do_gml3_extent_test(char * in, char * out, char * srs, lwgeom_free(g); } - static void out_gml_test_precision(void) { /* GML2 - 0 precision, i.e a round */ @@ -442,19 +441,6 @@ static void out_gml_test_dims(void) static void out_gml_test_geoms(void) { - /* GML2 - LINESTRING EMPTY - do_gml2_test( - "LINESTRING EMPTY", - "", - NULL, 0); - */ - - /* GML2 - POLYGON EMPTY */ - do_gml2_test( - "POLYGON EMPTY", - "", - NULL, 0); - /* GML2 - Linestring */ do_gml2_test( "LINESTRING(0 1,2 3,4 5)", @@ -552,18 +538,6 @@ static void out_gml_test_geoms(void) NULL, 0, 0); - /* GML2 - Empty GeometryCollection */ - do_gml2_test( - "GEOMETRYCOLLECTION EMPTY", - "", - NULL, 0); - - /* GML3 - Empty GeometryCollection */ - do_gml3_test( - "GEOMETRYCOLLECTION EMPTY", - "", - NULL, 0, 0); - /* GML2 - Nested GeometryCollection */ do_gml2_test( "GEOMETRYCOLLECTION(POINT(0 1),GEOMETRYCOLLECTION(LINESTRING(2 3,4 5)))", @@ -751,13 +725,13 @@ static void out_gml_test_geoms_prefix(void) /* GML2 - Empty GeometryCollection */ do_gml2_test_prefix( "GEOMETRYCOLLECTION EMPTY", - "", + "", NULL, 0, "custom:"); /* GML3 - Empty GeometryCollection */ do_gml3_test_prefix( "GEOMETRYCOLLECTION EMPTY", - "", + "", NULL, 0, 0, "custom:"); /* GML2 - Nested GeometryCollection */ @@ -885,13 +859,13 @@ static void out_gml_test_geoms_prefix(void) /* GML2 - Empty GeometryCollection */ do_gml2_test_prefix( "GEOMETRYCOLLECTION EMPTY", - "", + "", NULL, 0, ""); /* GML3 - Empty GeometryCollection */ do_gml3_test_prefix( "GEOMETRYCOLLECTION EMPTY", - "", + "", NULL, 0, 0, ""); /* GML2 - Nested GeometryCollection */ @@ -1130,6 +1104,51 @@ static void out_gml3_extent(void) } +static void out_gml_test_empty(void) +{ + /* POINT EMPTY, GML2 */ + do_gml2_test("POINT EMPTY", "", NULL, 0); + + /* POINT EMPTY, GML3 */ + do_gml3_test("POINT EMPTY", "", NULL, 0, 0); + + /* LINESTRING EMPTY, GML2 */ + do_gml2_test("LINESTRING EMPTY", "", NULL, 0); + + /* LINESTRING EMPTY, GML3 */ + do_gml3_test("LINESTRING EMPTY", "", NULL, 0, 0); + + /* POLYGON EMPTY, GML2 */ + do_gml2_test("POLYGON EMPTY", "", NULL, 0); + + /* POLYGON EMPTY, GML3 */ + do_gml3_test("POLYGON EMPTY", "", NULL, 0, 0); + + /* MULTIPOINT EMPTY, GML2 */ + do_gml2_test("MULTIPOINT EMPTY", "", NULL, 0); + + /* MULTIPOINT EMPTY, GML3 */ + do_gml3_test("MULTIPOINT EMPTY", "", NULL, 0, 0); + + /* MULTILINESTRING EMPTY, GML2 */ + do_gml2_test("MULTILINESTRING EMPTY", "", NULL, 0); + + /* MULTILINESTRING EMPTY, GML3 */ + do_gml3_test("MULTILINESTRING EMPTY", "", NULL, 0, 0); + + /* MULTIPOLYGON EMPTY, GML2 */ + do_gml2_test("MULTIPOLYGON EMPTY", "", NULL, 0); + + /* MULTIPOLYGON EMPTY, GML3 */ + do_gml3_test("MULTIPOLYGON EMPTY", "", NULL, 0, 0); + + /* GEOMETRYCOLLECTION EMPTY, GML2 */ + do_gml2_test("GEOMETRYCOLLECTION EMPTY", "", NULL, 0); + + /* GEOMETRYCOLLECTION EMPTY, GML3 */ + do_gml3_test("GEOMETRYCOLLECTION EMPTY", "", NULL, 0, 0); + +} /* @@ -1146,6 +1165,7 @@ CU_TestInfo out_gml_tests[] = PG_TEST(out_gml_test_geoms_nodims), PG_TEST(out_gml2_extent), PG_TEST(out_gml3_extent), + PG_TEST(out_gml_test_empty), CU_TEST_INFO_NULL }; -CU_SuiteInfo out_gml_suite = {"GML Out Suite", NULL, NULL, out_gml_tests}; +CU_SuiteInfo out_gml_suite = {"out_gml", NULL, NULL, out_gml_tests}; diff --git a/liblwgeom/lwout_gml.c b/liblwgeom/lwout_gml.c index 79046a597..4d390f6d3 100644 --- a/liblwgeom/lwout_gml.c +++ b/liblwgeom/lwout_gml.c @@ -255,14 +255,13 @@ asgml2_point_buf(const LWPOINT *point, const char *srs, char *output, int precis { char *ptr = output; - if ( srs ) - { - ptr += sprintf(ptr, "<%sPoint srsName=\"%s\">", prefix, srs); - } - else - { - ptr += sprintf(ptr, "<%sPoint>", prefix); + ptr += sprintf(ptr, "<%sPoint", prefix); + if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs); + if ( lwpoint_is_empty(point) ) { + ptr += sprintf(ptr, "/>"); + return (ptr-output); } + ptr += sprintf(ptr, ">"); ptr += sprintf(ptr, "<%scoordinates>", prefix); ptr += pointArray_toGML2(point->point, ptr, precision); ptr += sprintf(ptr, "", prefix, prefix); @@ -300,14 +299,15 @@ asgml2_line_buf(const LWLINE *line, const char *srs, char *output, int precision { char *ptr=output; - if ( srs ) - { - ptr += sprintf(ptr, "<%sLineString srsName=\"%s\">", prefix, srs); - } - else - { - ptr += sprintf(ptr, "<%sLineString>", prefix); + ptr += sprintf(ptr, "<%sLineString", prefix); + if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs); + + if ( lwline_is_empty(line) ) { + ptr += sprintf(ptr, "/>"); + return (ptr-output); } + ptr += sprintf(ptr, ">"); + ptr += sprintf(ptr, "<%scoordinates>", prefix); ptr += pointArray_toGML2(line->points, ptr, precision); ptr += sprintf(ptr, "", prefix, prefix); @@ -354,26 +354,22 @@ asgml2_poly_buf(const LWPOLY *poly, const char *srs, char *output, int precision int i; char *ptr=output; - if ( srs ) - { - ptr += sprintf(ptr, "<%sPolygon srsName=\"%s\">", prefix, srs); + ptr += sprintf(ptr, "<%sPolygon", prefix); + if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs); + if ( lwpoly_is_empty(poly) ) { + ptr += sprintf(ptr, "/>"); + return (ptr-output); } - else + ptr += sprintf(ptr, ">"); + ptr += sprintf(ptr, "<%souterBoundaryIs><%sLinearRing><%scoordinates>", + prefix, prefix, prefix); + ptr += pointArray_toGML2(poly->rings[0], ptr, precision); + ptr += sprintf(ptr, "", prefix, prefix, prefix); + for (i=1; inrings; i++) { - ptr += sprintf(ptr, "<%sPolygon>", prefix); - } - if ( ! lwpoly_is_empty(poly) ) - { - ptr += sprintf(ptr, "<%souterBoundaryIs><%sLinearRing><%scoordinates>", - prefix, prefix, prefix); - ptr += pointArray_toGML2(poly->rings[0], ptr, precision); - ptr += sprintf(ptr, "", prefix, prefix, prefix); - for (i=1; inrings; i++) - { - ptr += sprintf(ptr, "<%sinnerBoundaryIs><%sLinearRing><%scoordinates>", prefix, prefix, prefix); - ptr += pointArray_toGML2(poly->rings[i], ptr, precision); - ptr += sprintf(ptr, "", prefix, prefix, prefix); - } + ptr += sprintf(ptr, "<%sinnerBoundaryIs><%sLinearRing><%scoordinates>", prefix, prefix, prefix); + ptr += pointArray_toGML2(poly->rings[i], ptr, precision); + ptr += sprintf(ptr, "", prefix, prefix, prefix); } ptr += sprintf(ptr, "", prefix); @@ -455,14 +451,14 @@ asgml2_multi_buf(const LWCOLLECTION *col, const char *srs, char *output, else if (type == MULTIPOLYGONTYPE) gmltype = "MultiPolygon"; /* Open outmost tag */ - if ( srs ) - { - ptr += sprintf(ptr, "<%s%s srsName=\"%s\">", prefix, gmltype, srs); - } - else - { - ptr += sprintf(ptr, "<%s%s>", prefix, gmltype); + ptr += sprintf(ptr, "<%s%s", prefix, gmltype); + if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs); + + if (!col->ngeoms) { + ptr += sprintf(ptr, "/>"); + return (ptr-output); } + ptr += sprintf(ptr, ">"); for (i=0; ingeoms; i++) { @@ -569,14 +565,14 @@ asgml2_collection_buf(const LWCOLLECTION *col, const char *srs, char *output, in ptr = output; /* Open outmost tag */ - if ( srs ) - { - ptr += sprintf(ptr, "<%sMultiGeometry srsName=\"%s\">", prefix, srs); - } - else - { - ptr += sprintf(ptr, "<%sMultiGeometry>", prefix); + ptr += sprintf(ptr, "<%sMultiGeometry", prefix); + if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs); + + if (!col->ngeoms) { + ptr += sprintf(ptr, "/>"); + return (ptr-output); } + ptr += sprintf(ptr, ">"); for (i=0; ingeoms; i++) { @@ -761,14 +757,15 @@ asgml3_point_buf(const LWPOINT *point, const char *srs, char *output, int precis int dimension=2; if (FLAGS_GET_Z(point->flags)) dimension = 3; - if ( srs ) - { - ptr += sprintf(ptr, "<%sPoint srsName=\"%s\">", prefix, srs); - } - else - { - ptr += sprintf(ptr, "<%sPoint>", prefix); + + ptr += sprintf(ptr, "<%sPoint", prefix); + if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs); + if ( lwpoint_is_empty(point) ) { + ptr += sprintf(ptr, "/>"); + return (ptr-output); } + + ptr += sprintf(ptr, ">"); if (IS_DIMS(opts)) ptr += sprintf(ptr, "<%spos srsDimension=\"%d\">", prefix, dimension); else ptr += sprintf(ptr, "<%spos>", prefix); ptr += pointArray_toGML3(point->point, ptr, precision, opts); @@ -832,10 +829,13 @@ asgml3_line_buf(const LWLINE *line, const char *srs, char *output, int precision } if ( srs ) { - ptr += sprintf(ptr, " srsName=\"%s\">", srs); - } else { - ptr += sprintf(ptr, ">"); + ptr += sprintf(ptr, " srsName=\"%s\"", srs); + } + if ( lwline_is_empty(line) ) { + ptr += sprintf(ptr, "/>"); + return (ptr-output); } + ptr += sprintf(ptr, ">"); if ( ! shortline ) { ptr += sprintf(ptr, "<%ssegments>", prefix); @@ -906,15 +906,22 @@ asgml3_poly_buf(const LWPOLY *poly, const char *srs, char *output, int precision if (FLAGS_GET_Z(poly->flags)) dimension = 3; if (is_patch) { - if (srs) ptr += sprintf(ptr, "<%sPolygonPatch srsName=\"%s\">", prefix, srs); - else ptr += sprintf(ptr, "<%sPolygonPatch>", prefix); + ptr += sprintf(ptr, "<%sPolygonPatch", prefix); + } else { - if (srs) ptr += sprintf(ptr, "<%sPolygon srsName=\"%s\">", prefix, srs); - else ptr += sprintf(ptr, "<%sPolygon>", prefix); + ptr += sprintf(ptr, "<%sPolygon", prefix); } + if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs); + + if ( lwpoly_is_empty(poly) ) { + ptr += sprintf(ptr, "/>"); + return (ptr-output); + } + ptr += sprintf(ptr, ">"); + ptr += sprintf(ptr, "<%sexterior><%sLinearRing>", prefix, prefix); if (IS_DIMS(opts)) ptr += sprintf(ptr, "<%sposList srsDimension=\"%d\">", prefix, dimension); else ptr += sprintf(ptr, "<%sposList>", prefix); @@ -1062,14 +1069,14 @@ asgml3_multi_buf(const LWCOLLECTION *col, const char *srs, char *output, int pre else if (type == MULTIPOLYGONTYPE) gmltype = "MultiSurface"; /* Open outmost tag */ - if ( srs ) - { - ptr += sprintf(ptr, "<%s%s srsName=\"%s\">", prefix, gmltype, srs); - } - else - { - ptr += sprintf(ptr, "<%s%s>", prefix, gmltype); + ptr += sprintf(ptr, "<%s%s", prefix, gmltype); + if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs); + + if (!col->ngeoms) { + ptr += sprintf(ptr, "/>"); + return (ptr-output); } + ptr += sprintf(ptr, ">"); for (i=0; ingeoms; i++) { @@ -1292,14 +1299,14 @@ asgml3_collection_buf(const LWCOLLECTION *col, const char *srs, char *output, in ptr = output; /* Open outmost tag */ - if ( srs ) - { - ptr += sprintf(ptr, "<%sMultiGeometry srsName=\"%s\">", prefix, srs); - } - else - { - ptr += sprintf(ptr, "<%sMultiGeometry>", prefix); + ptr += sprintf(ptr, "<%sMultiGeometry", prefix); + if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs); + + if (!col->ngeoms) { + ptr += sprintf(ptr, "/>"); + return (ptr-output); } + ptr += sprintf(ptr, ">"); for (i=0; ingeoms; i++) { diff --git a/regress/empty.sql b/regress/empty.sql index 0fa92fd95..6085cb022 100644 --- a/regress/empty.sql +++ b/regress/empty.sql @@ -17,16 +17,15 @@ SELECT 'T3.3', ST_AsGML('POLYGON EMPTY'); SELECT 'T3.4', ST_AsGML('MULTIPOLYGON EMPTY'); SELECT 'T3.5', ST_AsGML('MULTILINESTRING EMPTY'); SELECT 'T3.6', ST_AsGML('GEOMETRYCOLLECTION EMPTY'); --- There's a crash somewhere in here... ---SELECT 'T3.7', ST_AsGML(3,'POINT EMPTY'::geometry); ---SELECT 'T3.8', ST_AsGML(3,'LINESTRING EMPTY'::geometry); ---SELECT 'T3.9', ST_AsGML(3,'POLYGON EMPTY'::geometry); ---SELECT 'T3.10', ST_AsGML(3,'MULTIPOLYGON EMPTY'::geometry); ---SELECT 'T3.11', ST_AsGML(3,'MULTILINESTRING EMPTY'::geometry); ---SELECT 'T3.12', ST_AsGML(3,'GEOMETRYCOLLECTION EMPTY'::geometry); ---SELECT 'T3.13', ST_AsGML(3,'POINT EMPTY'::geometry); ---SELECT 'T3.14', ST_AsGML(3,'LINESTRING EMPTY'::geometry); ---SELECT 'T3.15', ST_AsGML(3,'POLYGON EMPTY'::geometry); ---SELECT 'T3.16', ST_AsGML(3,'MULTIPOLYGON EMPTY'::geometry); ---SELECT 'T3.17', ST_AsGML(3,'MULTILINESTRING EMPTY'::geometry); ---SELECT 'T3.18', ST_AsGML(3,'GEOMETRYCOLLECTION EMPTY'::geometry); +SELECT 'T3.7', ST_AsGML(3,'POINT EMPTY'::geometry); +SELECT 'T3.8', ST_AsGML(3,'LINESTRING EMPTY'::geometry); +SELECT 'T3.9', ST_AsGML(3,'POLYGON EMPTY'::geometry); +SELECT 'T3.10', ST_AsGML(3,'MULTIPOLYGON EMPTY'::geometry); +SELECT 'T3.11', ST_AsGML(3,'MULTILINESTRING EMPTY'::geometry); +SELECT 'T3.12', ST_AsGML(3,'GEOMETRYCOLLECTION EMPTY'::geometry); +SELECT 'T3.13', ST_AsGML(3,'POINT EMPTY'::geometry); +SELECT 'T3.14', ST_AsGML(3,'LINESTRING EMPTY'::geometry); +SELECT 'T3.15', ST_AsGML(3,'POLYGON EMPTY'::geometry); +SELECT 'T3.16', ST_AsGML(3,'MULTIPOLYGON EMPTY'::geometry); +SELECT 'T3.17', ST_AsGML(3,'MULTILINESTRING EMPTY'::geometry); +SELECT 'T3.18', ST_AsGML(3,'GEOMETRYCOLLECTION EMPTY'::geometry); diff --git a/regress/empty_expected b/regress/empty_expected index ac78a9e74..becccfec5 100644 --- a/regress/empty_expected +++ b/regress/empty_expected @@ -5,9 +5,21 @@ T2.1|SRID=4326;POLYGON EMPTY T2.2|SRID=4326;POLYGON EMPTY T2.3|SRID=4326;POLYGON EMPTY T2.4|4326|POLYGON -T3.1| -T3.2| -T3.3| -T3.4| -T3.5| -T3.6| +T3.1| +T3.2| +T3.3| +T3.4| +T3.5| +T3.6| +T3.7| +T3.8| +T3.9| +T3.10| +T3.11| +T3.12| +T3.13| +T3.14| +T3.15| +T3.16| +T3.17| +T3.18|