Skip to content
Permalink
Browse files

When creating geometry collections for GEOS, skip any empty parts

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 89d0211edf47262faf7abe7cbba19c3cc43643cb
Showing with 36 additions and 2 deletions.
  1. +12 −2 src/core/geometry/qgsgeos.cpp
  2. +24 −0 tests/src/core/testqgsgeometry.cpp
@@ -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;
@@ -52,6 +52,7 @@
#include "qgscurvepolygon.h"
#include "qgsproject.h"
#include "qgslinesegment.h"
#include "qgsgeos.h"

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

void geos();

// geometry types
void point(); //test QgsPointV2
@@ -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

0 comments on commit 89d0211

Please sign in to comment.
You can’t perform that action at this time.