Skip to content

Commit 08f2f41

Browse files
committed
Make geometry import/export more robust in case of invalid geometries. Fixes #12836
1 parent f39fbf4 commit 08f2f41

File tree

4 files changed

+76
-13
lines changed

4 files changed

+76
-13
lines changed

src/core/geometry/qgsgeometrycollectionv2.cpp

+25-8
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,24 @@ bool QgsGeometryCollectionV2::fromWkb( const unsigned char * wkb )
177177
wkbPtr >> mWkbType;
178178
int nGeometries = 0;
179179
wkbPtr >> nGeometries;
180-
mGeometries.resize( nGeometries );
180+
181+
QList<QgsAbstractGeometryV2*> geometryList;
181182
for ( int i = 0; i < nGeometries; ++i )
182183
{
183184
QgsAbstractGeometryV2* geom = QgsGeometryImport::geomFromWkb( wkbPtr );
184-
mGeometries[i] = geom;
185-
wkbPtr += geom->wkbSize();
185+
if ( geom )
186+
{
187+
geometryList.append( geom );
188+
wkbPtr += geom->wkbSize();
189+
}
190+
}
191+
192+
mGeometries.resize( geometryList.size() );
193+
for ( int i = 0; i < geometryList.size(); ++i )
194+
{
195+
mGeometries[i] = geometryList.at( i );
186196
}
197+
187198
return true;
188199
}
189200

@@ -198,7 +209,10 @@ int QgsGeometryCollectionV2::wkbSize() const
198209
int size = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 );
199210
foreach ( const QgsAbstractGeometryV2 *geom, mGeometries )
200211
{
201-
size += geom->wkbSize();
212+
if ( geom )
213+
{
214+
size += geom->wkbSize();
215+
}
202216
}
203217
return size;
204218
}
@@ -214,10 +228,13 @@ unsigned char* QgsGeometryCollectionV2::asWkb( int& binarySize ) const
214228
foreach ( const QgsAbstractGeometryV2 *geom, mGeometries )
215229
{
216230
int geomWkbLen = 0;
217-
unsigned char* geomWkb = geom->asWkb( geomWkbLen );
218-
memcpy( wkb, geomWkb, geomWkbLen );
219-
wkb += geomWkbLen;
220-
delete[] geomWkb;
231+
if ( geom )
232+
{
233+
unsigned char* geomWkb = geom->asWkb( geomWkbLen );
234+
memcpy( wkb, geomWkb, geomWkbLen );
235+
wkb += geomWkbLen;
236+
delete[] geomWkb;
237+
}
221238
}
222239
return geomPtr;
223240
}

src/core/geometry/qgsgeometryimport.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "qgscurvepolygonv2.h"
2222
#include "qgspointv2.h"
2323
#include "qgspolygonv2.h"
24+
#include "qgscurvepolygonv2.h"
2425
#include "qgslinestringv2.h"
2526
#include "qgsmulticurvev2.h"
2627
#include "qgsmultilinestringv2.h"
@@ -229,6 +230,12 @@ QgsAbstractGeometryV2* QgsGeometryImport::geomFromWkbType( QgsWKBTypes::Type t )
229230
return new QgsMultiPolygonV2();
230231
case QgsWKBTypes::MultiPoint:
231232
return new QgsMultiPointV2();
233+
case QgsWKBTypes::MultiCurve:
234+
return new QgsMultiCurveV2();
235+
case QgsWKBTypes::MultiSurface:
236+
return new QgsMultiSurfaceV2();
237+
case QgsWKBTypes::GeometryCollection:
238+
return new QgsGeometryCollectionV2();
232239
default:
233240
return 0;
234241
}

src/core/geometry/qgsgeos.cpp

+38-4
Original file line numberDiff line numberDiff line change
@@ -1009,12 +1009,42 @@ GEOSGeometry* QgsGeos::asGeos( const QgsAbstractGeometryV2* geom )
10091009
{
10101010
return 0;
10111011
}
1012-
GEOSGeometry **geomarr = new GEOSGeometry*[ c->numGeometries()];
1013-
for ( int i = 0; i < c->numGeometries(); ++i )
1012+
1013+
try
10141014
{
1015-
geomarr[i] = asGeos( c->geometryN( i ) );
1015+
1016+
//GEOSGeometry **geomarr = new GEOSGeometry*[ c->numGeometries()];
1017+
QList< GEOSGeometry* > validGeoms;
1018+
GEOSGeometry* geosGeom = 0;
1019+
for ( int i = 0; i < c->numGeometries(); ++i )
1020+
{
1021+
geosGeom = asGeos( c->geometryN( i ) );
1022+
if ( geosGeom )
1023+
{
1024+
validGeoms.append( geosGeom );
1025+
}
1026+
}
1027+
1028+
if ( validGeoms.size() < 1 )
1029+
{
1030+
return 0;
1031+
}
1032+
1033+
GEOSGeometry **geomarr = new GEOSGeometry*[ validGeoms.size()];
1034+
for ( int i = 0; i < validGeoms.size(); ++i )
1035+
{
1036+
geomarr[i] = validGeoms.at( i );
1037+
}
1038+
1039+
return GEOSGeom_createCollection_r( geosinit.ctxt, geosType, geomarr, validGeoms.size() );
1040+
}
1041+
1042+
catch ( GEOSException &e )
1043+
{
1044+
Q_UNUSED( e );
1045+
//delete?
1046+
return 0;
10161047
}
1017-
return GEOSGeom_createCollection_r( geosinit.ctxt, geosType, geomarr, c->numGeometries() ); //todo: geos exceptions
10181048
}
10191049

10201050
return 0;
@@ -1415,6 +1445,10 @@ GEOSGeometry* QgsGeos::createGeosPolygon( const QgsAbstractGeometryV2* poly )
14151445
return 0;
14161446

14171447
const QgsCurveV2* exteriorRing = polygon->exteriorRing();
1448+
if ( !exteriorRing )
1449+
{
1450+
return 0;
1451+
}
14181452
GEOSGeometry* exteriorRingGeos = GEOSGeom_createLinearRing_r( geosinit.ctxt, createCoordinateSequence( exteriorRing ) );
14191453

14201454
int nHoles = polygon->numInteriorRings();

src/core/geometry/qgspolygonv2.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,12 @@ bool QgsPolygonV2::fromWkb( const unsigned char* wkb )
4848
{
4949
QgsLineStringV2* line = new QgsLineStringV2();
5050
line->fromWkbPoints( mWkbType, wkbPtr );
51-
if ( i == 0 )
51+
if ( !line->isRing() )
52+
{
53+
delete line; continue;
54+
}
55+
56+
if ( !mExteriorRing )
5257
{
5358
mExteriorRing = line;
5459
}

0 commit comments

Comments
 (0)