Skip to content

Commit

Permalink
When creating geometry collections for GEOS, skip any empty parts
Browse files Browse the repository at this point in the history
These can cause crashes in GEOS functions

Fixes #37688

(cherry picked from commit 6ddff0d)
  • Loading branch information
nyalldawson committed Jul 10, 2020
1 parent 7ac65f3 commit 89d0211
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 2 deletions.
14 changes: 12 additions & 2 deletions src/core/geometry/qgsgeos.cpp
Expand Up @@ -1059,8 +1059,18 @@ geos::unique_ptr QgsGeos::createGeosCollection( int typeId, const QVector<GEOSGe
{
if ( *geomIt )
{
geomarr[i] = *geomIt;
++i;
if ( GEOSisEmpty_r( geosinit.ctxt, *geomIt ) )
{
// don't add empty parts to a geos collection, it can cause crashes in GEOS
nNullGeoms++;
nNotNullGeoms--;
GEOSGeom_destroy_r( geosinit.ctxt, *geomIt );
}
else
{
geomarr[i] = *geomIt;
++i;
}
}
}
geos::unique_ptr geom;
Expand Down
24 changes: 24 additions & 0 deletions tests/src/core/testqgsgeometry.cpp
Expand Up @@ -52,6 +52,7 @@
#include "qgscurvepolygon.h"
#include "qgsproject.h"
#include "qgslinesegment.h"
#include "qgsgeos.h"

//qgs unit test utility class
#include "qgsrenderchecker.h"
Expand Down Expand Up @@ -85,6 +86,7 @@ class TestQgsGeometry : public QObject
void vertexIterator();
void partIterator();

void geos();

// geometry types
void point(); //test QgsPointV2
Expand Down Expand Up @@ -522,6 +524,28 @@ void TestQgsGeometry::partIterator()
// See test_qgsgeometry.py for geometry-type specific checks!
}

void TestQgsGeometry::geos()
{
// test GEOS conversion utils

// empty parts should NOT be added to a GEOS collection -- it can cause crashes in GEOS
QgsMultiPolygon polyWithEmptyParts;
geos::unique_ptr asGeos( QgsGeos::asGeos( &polyWithEmptyParts ) );
QgsGeometry res( QgsGeos::fromGeos( asGeos.get() ) );
QCOMPARE( res.asWkt(), QStringLiteral( "MultiPolygon EMPTY" ) );
std::unique_ptr< QgsPolygon > emptyPolygon = qgis::make_unique< QgsPolygon >();
emptyPolygon->setExteriorRing( new QgsLineString() );
polyWithEmptyParts.addGeometry( emptyPolygon->clone() );
std::unique_ptr< QgsPolygon > nonEmptyPolygon = qgis::make_unique< QgsPolygon >();
nonEmptyPolygon->setExteriorRing( new QgsLineString( QVector< QgsPoint >() << QgsPoint( 0, 0 ) << QgsPoint( 0, 1 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 0 ) ) );
polyWithEmptyParts.addGeometry( nonEmptyPolygon->clone() );
polyWithEmptyParts.addGeometry( emptyPolygon->clone() );
asGeos = QgsGeos::asGeos( &polyWithEmptyParts );
QCOMPARE( GEOSGetNumGeometries_r( QgsGeos::getGEOSHandler(), asGeos.get() ), 1 );
res = QgsGeometry( QgsGeos::fromGeos( asGeos.get() ) );
QCOMPARE( res.asWkt(), QStringLiteral( "MultiPolygon (((0 0, 0 1, 1 1, 0 0)))" ) );
}

void TestQgsGeometry::point()
{
//test QgsPointV2
Expand Down

0 comments on commit 89d0211

Please sign in to comment.