[postgis-tickets] r17672 - ST_GeomFromGeoJSON crash on empty rings
Darafei
komzpa at gmail.com
Sun Aug 4 12:45:16 PDT 2019
Author: komzpa
Date: 2019-08-04 00:45:16 -0700 (Sun, 04 Aug 2019)
New Revision: 17672
Modified:
trunk/NEWS
trunk/liblwgeom/lwin_geojson.c
trunk/regress/core/in_geojson.sql
trunk/regress/core/in_geojson_expected
Log:
ST_GeomFromGeoJSON crash on empty rings
Closes #4470
Closes https://github.com/postgis/postgis/pull/453
Modified: trunk/NEWS
===================================================================
--- trunk/NEWS 2019-08-04 07:42:45 UTC (rev 17671)
+++ trunk/NEWS 2019-08-04 07:45:16 UTC (rev 17672)
@@ -220,7 +220,9 @@
- #4327, Avoid pfree'ing the result of getenv (Raúl Marín)
- #4406, Throw on invalid characters when decoding geohash (Raúl Marín)
- #4459, Fix ST_Subdivide crash on intermediate EMPTY (Darafei Praliaskouski)
+ - #4470, ST_GeomFromGeoJSON crash on empty rings (Darafei Praliaskouski)
+
PostGIS 2.5.0
2018/09/23
WARNING: If compiling with PostgreSQL+JIT, LLVM >= 6 is required
Modified: trunk/liblwgeom/lwin_geojson.c
===================================================================
--- trunk/liblwgeom/lwin_geojson.c 2019-08-04 07:42:45 UTC (rev 17671)
+++ trunk/liblwgeom/lwin_geojson.c 2019-08-04 07:45:16 UTC (rev 17672)
@@ -18,13 +18,12 @@
*
**********************************************************************
*
+ * Copyright 2019 Darafei Praliaskouski <me at komzpa.net>
* Copyright 2013 Sandro Santilli <strk at kbt.io>
* Copyright 2011 Kashif Rasul <kashif.rasul at gmail.com>
*
**********************************************************************/
-
-#include <assert.h>
#include "liblwgeom.h"
#include "lwgeom_log.h"
#include "../postgis_config.h"
@@ -41,29 +40,23 @@
#ifndef JSON_C_VERSION
/* Adds support for libjson < 0.10 */
-# define json_tokener_error_desc(x) json_tokener_errors[(x)]
+#define json_tokener_error_desc(x) json_tokener_errors[(x)]
#endif
#include <string.h>
-static void geojson_lwerror(char *msg, __attribute__((__unused__)) int error_code)
-{
- LWDEBUGF(3, "lwgeom_from_geojson ERROR %i", error_code);
- lwerror("%s", msg);
-}
-
/* Prototype */
-static LWGEOM* parse_geojson(json_object *geojson, int *hasz, int root_srid);
+static LWGEOM *parse_geojson(json_object *geojson, int *hasz);
-static json_object*
-findMemberByName(json_object* poObj, const char* pszName )
+static inline json_object *
+findMemberByName(json_object *poObj, const char *pszName)
{
- json_object* poTmp;
+ json_object *poTmp;
json_object_iter it;
poTmp = poObj;
- if( NULL == pszName || NULL == poObj)
+ if (!pszName || !poObj)
return NULL;
it.key = NULL;
@@ -70,21 +63,19 @@
it.val = NULL;
it.entry = NULL;
- if( NULL != json_object_get_object(poTmp) )
+ if (json_object_get_object(poTmp))
{
- if( NULL == json_object_get_object(poTmp)->head )
+ if (!json_object_get_object(poTmp)->head)
{
- geojson_lwerror("invalid GeoJSON representation", 2);
+ lwerror("invalid GeoJSON representation");
return NULL;
}
- for( it.entry = json_object_get_object(poTmp)->head;
- ( it.entry ?
- ( it.key = (char*)it.entry->k,
- it.val = (json_object*)it.entry->v, it.entry) : 0);
- it.entry = it.entry->next)
+ for (it.entry = json_object_get_object(poTmp)->head;
+ (it.entry ? (it.key = (char *)it.entry->k, it.val = (json_object *)it.entry->v, it.entry) : 0);
+ it.entry = it.entry->next)
{
- if( strcasecmp((char *)it.key, pszName )==0 )
+ if (strcasecmp((char *)it.key, pszName) == 0)
return it.val;
}
}
@@ -92,60 +83,56 @@
return NULL;
}
+static inline json_object *
+parse_coordinates(json_object *geojson)
+{
+ json_object *coordinates = findMemberByName(geojson, "coordinates");
+ if (!coordinates)
+ {
+ lwerror("Unable to find 'coordinates' in GeoJSON string");
+ return NULL;
+ }
-static int
+ if (json_type_array != json_object_get_type(coordinates))
+ {
+ lwerror("The 'coordinates' in GeoJSON are not an array");
+ return NULL;
+ }
+ return coordinates;
+}
+
+
+static inline int
parse_geojson_coord(json_object *poObj, int *hasz, POINTARRAY *pa)
{
- POINT4D pt;
+ POINT4D pt = {0, 0, 0, 0};
- LWDEBUGF(3, "parse_geojson_coord called for object %s.", json_object_to_json_string( poObj ) );
-
- if( json_type_array == json_object_get_type( poObj ) )
+ if (json_type_array == json_object_get_type(poObj))
{
- json_object* poObjCoord = NULL;
- const int nSize = json_object_array_length( poObj );
- LWDEBUGF(3, "parse_geojson_coord called for array size %d.", nSize );
-
- if ( nSize < 2 )
+ json_object *poObjCoord = NULL;
+ const int nSize = json_object_array_length(poObj);
+ if (nSize < 2)
{
- geojson_lwerror("Too few ordinates in GeoJSON", 4);
+ lwerror("Too few ordinates in GeoJSON");
return LW_FAILURE;
}
/* Read X coordinate */
- poObjCoord = json_object_array_get_idx( poObj, 0 );
- pt.x = json_object_get_double( poObjCoord );
- LWDEBUGF(3, "parse_geojson_coord pt.x = %f.", pt.x );
+ poObjCoord = json_object_array_get_idx(poObj, 0);
+ pt.x = json_object_get_double(poObjCoord);
/* Read Y coordinate */
- poObjCoord = json_object_array_get_idx( poObj, 1 );
- pt.y = json_object_get_double( poObjCoord );
- LWDEBUGF(3, "parse_geojson_coord pt.y = %f.", pt.y );
+ poObjCoord = json_object_array_get_idx(poObj, 1);
+ pt.y = json_object_get_double(poObjCoord);
- if( nSize > 2 ) /* should this be >= 3 ? */
+ if (nSize > 2) /* should this be >= 3 ? */
{
/* Read Z coordinate */
- poObjCoord = json_object_array_get_idx( poObj, 2 );
- pt.z = json_object_get_double( poObjCoord );
- LWDEBUGF(3, "parse_geojson_coord pt.z = %f.", pt.z );
+ poObjCoord = json_object_array_get_idx(poObj, 2);
+ pt.z = json_object_get_double(poObjCoord);
*hasz = LW_TRUE;
}
- else if ( nSize == 2 )
- {
- *hasz = LW_FALSE;
- /* Initialize Z coordinate, if required */
- if ( FLAGS_GET_Z(pa->flags) ) pt.z = 0.0;
- }
- else
- {
- /* TODO: should we account for nSize > 3 ? */
- /* more than 3 coordinates, we're just dropping dimensions here... */
- }
-
- /* Initialize M coordinate, if required */
- if ( FLAGS_GET_M(pa->flags) ) pt.m = 0.0;
-
}
else
{
@@ -156,126 +143,76 @@
return ptarray_append_point(pa, &pt, LW_TRUE);
}
-static LWGEOM*
-parse_geojson_point(json_object *geojson, int *hasz, int root_srid)
+static inline LWGEOM *
+parse_geojson_point(json_object *geojson, int *hasz)
{
- LWGEOM *geom;
- POINTARRAY *pa;
- json_object* coords = NULL;
-
- LWDEBUGF(3, "parse_geojson_point called with root_srid = %d.", root_srid );
-
- coords = findMemberByName( geojson, "coordinates" );
- if ( ! coords )
- {
- geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
- return NULL;
- }
-
- pa = ptarray_construct_empty(1, 0, 1);
+ json_object *coords = parse_coordinates(geojson);
+ POINTARRAY *pa = ptarray_construct_empty(1, 0, 1);
parse_geojson_coord(coords, hasz, pa);
-
- geom = (LWGEOM *) lwpoint_construct(root_srid, NULL, pa);
- LWDEBUG(2, "parse_geojson_point finished.");
- return geom;
+ return (LWGEOM *)lwpoint_construct(0, NULL, pa);
}
-static LWGEOM*
-parse_geojson_linestring(json_object *geojson, int *hasz, int root_srid)
+static inline LWGEOM *
+parse_geojson_linestring(json_object *geojson, int *hasz)
{
- LWGEOM *geom;
- POINTARRAY *pa;
- json_object* points = NULL;
- int i = 0;
-
- LWDEBUG(2, "parse_geojson_linestring called.");
-
- points = findMemberByName( geojson, "coordinates" );
- if ( ! points )
+ json_object *points = parse_coordinates(geojson);
+ POINTARRAY *pa = ptarray_construct_empty(1, 0, 1);
+ const int nPoints = json_object_array_length(points);
+ for (int i = 0; i < nPoints; i++)
{
- geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
- return NULL;
+ json_object *coords = json_object_array_get_idx(points, i);
+ parse_geojson_coord(coords, hasz, pa);
}
-
- pa = ptarray_construct_empty(1, 0, 1);
-
- if( json_type_array == json_object_get_type( points ) )
- {
- const int nPoints = json_object_array_length( points );
- for(i = 0; i < nPoints; ++i)
- {
- json_object* coords = NULL;
- coords = json_object_array_get_idx( points, i );
- parse_geojson_coord(coords, hasz, pa);
- }
- }
-
- geom = (LWGEOM *) lwline_construct(root_srid, NULL, pa);
-
- LWDEBUG(2, "parse_geojson_linestring finished.");
- return geom;
+ return (LWGEOM *)lwline_construct(0, NULL, pa);
}
-static LWGEOM*
-parse_geojson_polygon(json_object *geojson, int *hasz, int root_srid)
+static inline LWPOLY *
+parse_geojson_poly_rings(json_object *rings, int *hasz)
{
- POINTARRAY **ppa = NULL;
- json_object* rings = NULL;
- json_object* points = NULL;
- int i = 0, j = 0;
- int nRings = 0, nPoints = 0;
-
- rings = findMemberByName( geojson, "coordinates" );
- if ( ! rings )
- {
- geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
+ if (!rings)
return NULL;
- }
+ int nRings = json_object_array_length(rings);
- if ( json_type_array != json_object_get_type(rings) )
- {
- geojson_lwerror("The 'coordinates' in GeoJSON are not an array", 4);
- return NULL;
- }
+ /* No rings => POLYGON EMPTY */
+ if (!nRings)
+ return lwpoly_construct_empty(0, 1, 0);
- nRings = json_object_array_length( rings );
+ /* Expecting up to nRings otherwise */
+ POINTARRAY **ppa = (POINTARRAY **)lwalloc(sizeof(POINTARRAY *) * nRings);
+ int o = 0;
- /* No rings => POLYGON EMPTY */
- if ( ! nRings )
+ for (int i = 0; i < nRings; i++)
{
- return (LWGEOM *)lwpoly_construct_empty(root_srid, 0, 0);
- }
-
- for ( i = 0; i < nRings; i++ )
- {
- points = json_object_array_get_idx(rings, i);
- if ( ! points || json_object_get_type(points) != json_type_array )
+ json_object *points = json_object_array_get_idx(rings, i);
+ if (!points || json_object_get_type(points) != json_type_array)
{
- geojson_lwerror("The 'coordinates' in GeoJSON ring are not an array", 4);
+ lwerror("The 'coordinates' in GeoJSON ring are not an array");
return NULL;
}
- nPoints = json_object_array_length(points);
+ int nPoints = json_object_array_length(points);
/* Skip empty rings */
- if ( nPoints == 0 ) continue;
+ if (!nPoints)
+ {
+ /* Empty outer? Don't promote first hole to outer, holes don't matter. */
+ if (!i)
+ break;
+ else
+ continue;
+ }
- if ( ! ppa )
- ppa = (POINTARRAY**)lwalloc(sizeof(POINTARRAY*) * nRings);
-
- ppa[i] = ptarray_construct_empty(1, 0, 1);
- for ( j = 0; j < nPoints; j++ )
+ ppa[o++] = ptarray_construct_empty(1, 0, 1);
+ for (int j = 0; j < nPoints; j++)
{
- json_object* coords = NULL;
- coords = json_object_array_get_idx( points, j );
+ json_object *coords = NULL;
+ coords = json_object_array_get_idx(points, j);
if (LW_FAILURE == parse_geojson_coord(coords, hasz, ppa[i]))
{
int k;
- for (k = 0; k <= i; k++)
- {
+ for (k = 0; k < o; k++)
ptarray_free(ppa[k]);
- }
lwfree(ppa);
- geojson_lwerror("The 'coordinates' in GeoJSON polygon are not sufficiently nested", 4);
+ lwerror("The 'coordinates' in GeoJSON are not sufficiently nested");
return NULL;
}
}
@@ -282,202 +219,102 @@
}
/* All the rings were empty! */
- if ( ! ppa )
- return (LWGEOM *)lwpoly_construct_empty(root_srid, 0, 0);
+ if (!o)
+ {
+ lwfree(ppa);
+ return lwpoly_construct_empty(0, 1, 0);
+ }
- return (LWGEOM *) lwpoly_construct(root_srid, NULL, nRings, ppa);
+ return lwpoly_construct(0, NULL, o, ppa);
}
-static LWGEOM*
-parse_geojson_multipoint(json_object *geojson, int *hasz, int root_srid)
+static inline LWGEOM *
+parse_geojson_polygon(json_object *geojson, int *hasz)
{
- LWGEOM *geom;
- int i = 0;
- json_object* poObjPoints = NULL;
+ return (LWGEOM *)parse_geojson_poly_rings(parse_coordinates(geojson), hasz);
+}
- if (!root_srid)
- {
- geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOINTTYPE, root_srid, 1, 0);
- }
- else
- {
- geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOINTTYPE, -1, 1, 0);
- }
+static inline LWGEOM *
+parse_geojson_multipoint(json_object *geojson, int *hasz)
+{
+ json_object *points = parse_coordinates(geojson);
+ LWMPOINT *geom = (LWMPOINT *)lwcollection_construct_empty(MULTIPOINTTYPE, 0, 1, 0);
- poObjPoints = findMemberByName( geojson, "coordinates" );
- if ( ! poObjPoints )
+ const int nPoints = json_object_array_length(points);
+ for (int i = 0; i < nPoints; ++i)
{
- geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
- return NULL;
+ POINTARRAY *pa = ptarray_construct_empty(1, 0, 1);
+ json_object *coord = json_object_array_get_idx(points, i);
+ parse_geojson_coord(coord, hasz, pa);
+ geom = lwmpoint_add_lwpoint(geom, lwpoint_construct(0, NULL, pa));
}
- if( json_type_array == json_object_get_type( poObjPoints ) )
- {
- const int nPoints = json_object_array_length( poObjPoints );
- for( i = 0; i < nPoints; ++i)
- {
- POINTARRAY *pa;
- json_object* poObjCoords = NULL;
- poObjCoords = json_object_array_get_idx( poObjPoints, i );
-
- pa = ptarray_construct_empty(1, 0, 1);
- parse_geojson_coord(poObjCoords, hasz, pa);
-
- geom = (LWGEOM*)lwmpoint_add_lwpoint((LWMPOINT*)geom,
- (LWPOINT*)lwpoint_construct(root_srid, NULL, pa));
- }
- }
-
- return geom;
+ return (LWGEOM *)geom;
}
-static LWGEOM*
-parse_geojson_multilinestring(json_object *geojson, int *hasz, int root_srid)
+static inline LWGEOM *
+parse_geojson_multilinestring(json_object *geojson, int *hasz)
{
- LWGEOM *geom = NULL;
- int i, j;
- json_object* poObjLines = NULL;
-
- if (!root_srid)
+ json_object *poObjLines = parse_coordinates(geojson);
+ LWMLINE *geom = (LWMLINE *)lwcollection_construct_empty(MULTILINETYPE, 0, 1, 0);
+ const int nLines = json_object_array_length(poObjLines);
+ for (int i = 0; i < nLines; ++i)
{
- geom = (LWGEOM *)lwcollection_construct_empty(MULTILINETYPE, root_srid, 1, 0);
- }
- else
- {
- geom = (LWGEOM *)lwcollection_construct_empty(MULTILINETYPE, -1, 1, 0);
- }
+ POINTARRAY *pa = ptarray_construct_empty(1, 0, 1);
+ json_object *poObjLine = json_object_array_get_idx(poObjLines, i);
- poObjLines = findMemberByName( geojson, "coordinates" );
- if ( ! poObjLines )
- {
- geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
- return NULL;
- }
-
- if( json_type_array == json_object_get_type( poObjLines ) )
- {
- const int nLines = json_object_array_length( poObjLines );
- for( i = 0; i < nLines; ++i)
+ if (json_type_array == json_object_get_type(poObjLine))
{
- POINTARRAY *pa = NULL;
- json_object* poObjLine = NULL;
- poObjLine = json_object_array_get_idx( poObjLines, i );
- pa = ptarray_construct_empty(1, 0, 1);
-
- if( json_type_array == json_object_get_type( poObjLine ) )
+ const int nPoints = json_object_array_length(poObjLine);
+ for (int j = 0; j < nPoints; ++j)
{
- const int nPoints = json_object_array_length( poObjLine );
- for(j = 0; j < nPoints; ++j)
- {
- json_object* coords = NULL;
- coords = json_object_array_get_idx( poObjLine, j );
- parse_geojson_coord(coords, hasz, pa);
- }
+ json_object *coords = json_object_array_get_idx(poObjLine, j);
+ parse_geojson_coord(coords, hasz, pa);
+ }
- geom = (LWGEOM*)lwmline_add_lwline((LWMLINE*)geom,
- (LWLINE*)lwline_construct(root_srid, NULL, pa));
- }
+ geom = lwmline_add_lwline(geom, lwline_construct(0, NULL, pa));
}
}
- return geom;
+ return (LWGEOM *)geom;
}
-static LWGEOM*
-parse_geojson_multipolygon(json_object *geojson, int *hasz, int root_srid)
+static inline LWGEOM *
+parse_geojson_multipolygon(json_object *geojson, int *hasz)
{
- LWGEOM *geom = NULL;
- int i, j, k;
- json_object* poObjPolys = NULL;
+ LWGEOM *geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOLYGONTYPE, 0, 1, 0);
+ json_object *polys = parse_coordinates(geojson);
+ int nPolys = json_object_array_length(polys);
- if (!root_srid)
+ for (int i = 0; i < nPolys; ++i)
{
- geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOLYGONTYPE, root_srid, 1, 0);
+ json_object *rings = json_object_array_get_idx(polys, i);
+ LWPOLY *poly = parse_geojson_poly_rings(rings, hasz);
+ geom = (LWGEOM *)lwmpoly_add_lwpoly((LWMPOLY *)geom, poly);
}
- else
- {
- geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOLYGONTYPE, -1, 1, 0);
- }
- poObjPolys = findMemberByName( geojson, "coordinates" );
- if ( ! poObjPolys )
- {
- geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
- return NULL;
- }
-
- if( json_type_array == json_object_get_type( poObjPolys ) )
- {
- const int nPolys = json_object_array_length( poObjPolys );
-
- for(i = 0; i < nPolys; ++i)
- {
- json_object* poObjPoly = json_object_array_get_idx( poObjPolys, i );
-
- if( json_type_array == json_object_get_type( poObjPoly ) )
- {
- LWPOLY *lwpoly = lwpoly_construct_empty(geom->srid, lwgeom_has_z(geom), lwgeom_has_m(geom));
- int nRings = json_object_array_length( poObjPoly );
-
- for(j = 0; j < nRings; ++j)
- {
- json_object* points = json_object_array_get_idx( poObjPoly, j );
-
- if( json_type_array == json_object_get_type( points ) )
- {
-
- POINTARRAY *pa = ptarray_construct_empty(1, 0, 1);
-
- int nPoints = json_object_array_length( points );
- for ( k=0; k < nPoints; k++ )
- {
- json_object* coords = json_object_array_get_idx( points, k );
- parse_geojson_coord(coords, hasz, pa);
- }
-
- lwpoly_add_ring(lwpoly, pa);
- }
- }
- geom = (LWGEOM*)lwmpoly_add_lwpoly((LWMPOLY*)geom, lwpoly);
- }
- }
- }
-
return geom;
}
-static LWGEOM*
-parse_geojson_geometrycollection(json_object *geojson, int *hasz, int root_srid)
+static inline LWGEOM *
+parse_geojson_geometrycollection(json_object *geojson, int *hasz)
{
- LWGEOM *geom = NULL;
- int i;
- json_object* poObjGeoms = NULL;
-
- if (!root_srid)
+ LWGEOM *geom = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, 0, 1, 0);
+ json_object *poObjGeoms = findMemberByName(geojson, "geometries");
+ if (!poObjGeoms)
{
- geom = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, root_srid, 1, 0);
- }
- else
- {
- geom = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, -1, 1, 0);
- }
-
- poObjGeoms = findMemberByName( geojson, "geometries" );
- if ( ! poObjGeoms )
- {
- geojson_lwerror("Unable to find 'geometries' in GeoJSON string", 4);
+ lwerror("Unable to find 'geometries' in GeoJSON string");
return NULL;
}
- if( json_type_array == json_object_get_type( poObjGeoms ) )
+ if (json_type_array == json_object_get_type(poObjGeoms))
{
- const int nGeoms = json_object_array_length( poObjGeoms );
- json_object* poObjGeom = NULL;
- for(i = 0; i < nGeoms; ++i )
+ const int nGeoms = json_object_array_length(poObjGeoms);
+ for (int i = 0; i < nGeoms; ++i)
{
- poObjGeom = json_object_array_get_idx( poObjGeoms, i );
- geom = (LWGEOM*)lwcollection_add_lwgeom((LWCOLLECTION *)geom,
- parse_geojson(poObjGeom, hasz, root_srid));
+ json_object *poObjGeom = json_object_array_get_idx(poObjGeoms, i);
+ geom = (LWGEOM *)lwcollection_add_lwgeom((LWCOLLECTION *)geom,
+ parse_geojson(poObjGeom, hasz));
}
}
@@ -484,47 +321,47 @@
return geom;
}
-static LWGEOM*
-parse_geojson(json_object *geojson, int *hasz, int root_srid)
+static inline LWGEOM *
+parse_geojson(json_object *geojson, int *hasz)
{
- json_object* type = NULL;
- const char* name;
+ json_object *type = NULL;
+ const char *name;
- if( NULL == geojson )
+ if (!geojson)
{
- geojson_lwerror("invalid GeoJSON representation", 2);
+ lwerror("invalid GeoJSON representation");
return NULL;
}
- type = findMemberByName( geojson, "type" );
- if( NULL == type )
+ type = findMemberByName(geojson, "type");
+ if (!type)
{
- geojson_lwerror("unknown GeoJSON type", 3);
+ lwerror("unknown GeoJSON type");
return NULL;
}
- name = json_object_get_string( type );
+ name = json_object_get_string(type);
- if( strcasecmp( name, "Point" )==0 )
- return parse_geojson_point(geojson, hasz, root_srid);
+ if (strcasecmp(name, "Point") == 0)
+ return parse_geojson_point(geojson, hasz);
- if( strcasecmp( name, "LineString" )==0 )
- return parse_geojson_linestring(geojson, hasz, root_srid);
+ if (strcasecmp(name, "LineString") == 0)
+ return parse_geojson_linestring(geojson, hasz);
- if( strcasecmp( name, "Polygon" )==0 )
- return parse_geojson_polygon(geojson, hasz, root_srid);
+ if (strcasecmp(name, "Polygon") == 0)
+ return parse_geojson_polygon(geojson, hasz);
- if( strcasecmp( name, "MultiPoint" )==0 )
- return parse_geojson_multipoint(geojson, hasz, root_srid);
+ if (strcasecmp(name, "MultiPoint") == 0)
+ return parse_geojson_multipoint(geojson, hasz);
- if( strcasecmp( name, "MultiLineString" )==0 )
- return parse_geojson_multilinestring(geojson, hasz, root_srid);
+ if (strcasecmp(name, "MultiLineString") == 0)
+ return parse_geojson_multilinestring(geojson, hasz);
- if( strcasecmp( name, "MultiPolygon" )==0 )
- return parse_geojson_multipolygon(geojson, hasz, root_srid);
+ if (strcasecmp(name, "MultiPolygon") == 0)
+ return parse_geojson_multipolygon(geojson, hasz);
- if( strcasecmp( name, "GeometryCollection" )==0 )
- return parse_geojson_geometrycollection(geojson, hasz, root_srid);
+ if (strcasecmp(name, "GeometryCollection") == 0)
+ return parse_geojson_geometrycollection(geojson, hasz);
lwerror("invalid GeoJson representation");
return NULL; /* Never reach */
@@ -532,7 +369,7 @@
#endif /* HAVE_LIBJSON or HAVE_LIBJSON_C --} */
-LWGEOM*
+LWGEOM *
lwgeom_from_geojson(const char *geojson, char **srs)
{
#ifndef HAVE_LIBJSON
@@ -539,45 +376,37 @@
*srs = NULL;
lwerror("You need JSON-C for lwgeom_from_geojson");
return NULL;
-#else /* HAVE_LIBJSON */
+#else /* HAVE_LIBJSON */
- /* size_t geojson_size = strlen(geojson); */
-
- LWGEOM *lwgeom;
- int hasz=LW_TRUE;
- json_tokener* jstok = NULL;
- json_object* poObj = NULL;
- json_object* poObjSrs = NULL;
- *srs = NULL;
-
/* Begin to Parse json */
- jstok = json_tokener_new();
- poObj = json_tokener_parse_ex(jstok, geojson, -1);
- if( jstok->err != json_tokener_success)
+ json_tokener *jstok = json_tokener_new();
+ json_object *poObj = json_tokener_parse_ex(jstok, geojson, -1);
+ if (jstok->err != json_tokener_success)
{
char err[256];
snprintf(err, 256, "%s (at offset %d)", json_tokener_error_desc(jstok->err), jstok->char_offset);
json_tokener_free(jstok);
json_object_put(poObj);
- geojson_lwerror(err, 1);
+ lwerror(err);
return NULL;
}
json_tokener_free(jstok);
- poObjSrs = findMemberByName( poObj, "crs" );
+ *srs = NULL;
+ json_object *poObjSrs = findMemberByName(poObj, "crs");
if (poObjSrs != NULL)
{
- json_object* poObjSrsType = findMemberByName( poObjSrs, "type" );
+ json_object *poObjSrsType = findMemberByName(poObjSrs, "type");
if (poObjSrsType != NULL)
{
- json_object* poObjSrsProps = findMemberByName( poObjSrs, "properties" );
- if ( poObjSrsProps )
+ json_object *poObjSrsProps = findMemberByName(poObjSrs, "properties");
+ if (poObjSrsProps)
{
- json_object* poNameURL = findMemberByName( poObjSrsProps, "name" );
- if ( poNameURL )
+ json_object *poNameURL = findMemberByName(poObjSrsProps, "name");
+ if (poNameURL)
{
- const char* pszName = json_object_get_string( poNameURL );
- if ( pszName )
+ const char *pszName = json_object_get_string(poNameURL);
+ if (pszName)
{
*srs = lwalloc(strlen(pszName) + 1);
strcpy(*srs, pszName);
@@ -587,22 +416,17 @@
}
}
- lwgeom = parse_geojson(poObj, &hasz, 0);
+ int hasz = LW_FALSE;
+ LWGEOM *lwgeom = parse_geojson(poObj, &hasz);
json_object_put(poObj);
- lwgeom_add_bbox(lwgeom);
-
if (!hasz)
{
LWGEOM *tmp = lwgeom_force_2d(lwgeom);
lwgeom_free(lwgeom);
lwgeom = tmp;
-
- LWDEBUG(2, "geom_from_geojson called.");
}
-
+ lwgeom_add_bbox(lwgeom);
return lwgeom;
#endif /* HAVE_LIBJSON } */
}
-
-
Modified: trunk/regress/core/in_geojson.sql
===================================================================
--- trunk/regress/core/in_geojson.sql 2019-08-04 07:42:45 UTC (rev 17671)
+++ trunk/regress/core/in_geojson.sql 2019-08-04 07:45:16 UTC (rev 17672)
@@ -47,8 +47,10 @@
SELECT 'geomfromgeojson_srs_3', ST_AsEWKT(ST_GeomFromGeoJSON('{"type":"GeometryCollection","geometries":[{"type":"Point","coordinates":[100.0,0.0]},{"type":"LineString","coordinates":[[101.0,0.0],[102.0,1.0]]}],"crs":{"type":"name","props":{"name":"urn:ogc:def:crs:EPSG::4326"}}}'));
SELECT 'geomfromgeojson_srs_4', ST_AsEWKT(ST_GeomFromGeoJSON('{"type":"GeometryCollection","geometries":[{"type":"Point","coordinates":[100.0,0.0]},{"type":"LineString","coordinates":[[101.0,0.0],[102.0,1.0]]}],"crs":{"type":"name","properties":{"nm":"EPSG:4326"}}}'));
--- #3583
SELECT '#3583', ST_AsText(ST_GeomFromGeoJSON('{"type":"MultiPolygon", "coordinates":[[[139.10030364990232,35.16777444430609],5842.4224490305424]]}'));
+SELECT '#4164', ST_AsText(ST_GeomFromGeoJSON('{"type": "Polygon", "coordinates": [[0,0],[0,5],[5, 5],[5,0],[0,0]]}'));
--- #4164
-SELECT ST_AsText(ST_GeomFromGeoJSON('{"type": "Polygon", "coordinates": [[0,0],[0,5],[5, 5],[5,0],[0,0]]}'));
+SELECT '#4470.a', ST_AsText(ST_GeomFromGeoJSON('{"type":"Polygon","coordinates":[[[0,0]],[]]}'));
+SELECT '#4470.b', ST_AsText(ST_GeomFromGeoJSON('{"type":"Polygon","coordinates":[[],[0,0]]}'));
+SELECT '#4470.c', ST_AsText(ST_GeomFromGeoJSON('{"type":"MultiPolygon","coordinates":[[[[0,0]],[]]]}'));
+SELECT '#4470.d', ST_AsText(ST_GeomFromGeoJSON('{"type":"MultiPolygon","coordinates":[[[],[0,0]]]}'));
Modified: trunk/regress/core/in_geojson_expected
===================================================================
--- trunk/regress/core/in_geojson_expected 2019-08-04 07:42:45 UTC (rev 17671)
+++ trunk/regress/core/in_geojson_expected 2019-08-04 07:45:16 UTC (rev 17672)
@@ -18,7 +18,7 @@
#2130|50
#2216|30
#2619|POLYGON EMPTY
-#2619|MULTIPOLYGON Z (EMPTY)
+#2619|MULTIPOLYGON EMPTY
ERROR: The 'coordinates' in GeoJSON ring are not an array
ERROR: The 'coordinates' in GeoJSON ring are not an array
geomfromgeojson_z_01|POINT(1 2 3)
@@ -29,5 +29,9 @@
geomfromgeojson_srs_2|GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1))
geomfromgeojson_srs_3|GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1))
geomfromgeojson_srs_4|GEOMETRYCOLLECTION(POINT(100 0),LINESTRING(101 0,102 1))
-#3583|MULTIPOLYGON Z (EMPTY)
-ERROR: The 'coordinates' in GeoJSON polygon are not sufficiently nested
+ERROR: The 'coordinates' in GeoJSON are not sufficiently nested
+ERROR: The 'coordinates' in GeoJSON are not sufficiently nested
+#4470.a|POLYGON((0 0))
+#4470.b|POLYGON EMPTY
+#4470.c|MULTIPOLYGON(((0 0)))
+#4470.d|MULTIPOLYGON EMPTY
More information about the postgis-tickets
mailing list