Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Try to fix crash on GEOS 3.8.1 when empty coordinate sequence is retu…
…rned

for a point geometry

Fixes #35719, fixes #35526
  • Loading branch information
nyalldawson committed Apr 15, 2020
1 parent 731aa90 commit 5ae631a
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/core/geometry/qgsgeos.cpp
Expand Up @@ -1095,7 +1095,9 @@ std::unique_ptr<QgsAbstractGeometry> QgsGeos::fromGeos( const GEOSGeometry *geos
case GEOS_POINT: // a point
{
const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosinit()->ctxt, geos );
return std::unique_ptr<QgsAbstractGeometry>( coordSeqPoint( cs, 0, hasZ, hasM ).clone() );
unsigned int nPoints = 0;
GEOSCoordSeq_getSize_r( geosinit()->ctxt, cs, &nPoints );
return nPoints > 0 ? std::unique_ptr<QgsAbstractGeometry>( coordSeqPoint( cs, 0, hasZ, hasM ).clone() ) : nullptr;
}
case GEOS_LINESTRING:
{
Expand All @@ -1115,7 +1117,10 @@ std::unique_ptr<QgsAbstractGeometry> QgsGeos::fromGeos( const GEOSGeometry *geos
const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosinit()->ctxt, GEOSGetGeometryN_r( geosinit()->ctxt, geos, i ) );
if ( cs )
{
multiPoint->addGeometry( coordSeqPoint( cs, 0, hasZ, hasM ).clone() );
unsigned int nPoints = 0;
GEOSCoordSeq_getSize_r( geosinit()->ctxt, cs, &nPoints );
if ( nPoints > 0 )
multiPoint->addGeometry( coordSeqPoint( cs, 0, hasZ, hasM ).clone() );
}
}
return std::move( multiPoint );
Expand Down
4 changes: 4 additions & 0 deletions src/core/pal/feature.cpp
Expand Up @@ -404,6 +404,10 @@ std::unique_ptr<LabelPosition> FeaturePart::createCandidatePointOnSurface( Point
{
const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, pointGeom.get() );
#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
unsigned int nPoints = 0;
GEOSCoordSeq_getSize_r( geosctxt, coordSeq, &nPoints );
if ( nPoints == 0 )
return nullptr;
GEOSCoordSeq_getXY_r( geosctxt, coordSeq, 0, &px, &py );
#else
GEOSCoordSeq_getX_r( geosctxt, coordSeq, 0, &px );
Expand Down
14 changes: 14 additions & 0 deletions src/core/pal/pointset.cpp
Expand Up @@ -819,6 +819,11 @@ double PointSet::minDistanceToPoint( double px, double py, double *rx, double *r
double nx;
double ny;
#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
unsigned int nPoints = 0;
GEOSCoordSeq_getSize_r( geosctxt, nearestCoord.get(), &nPoints );
if ( nPoints == 0 )
return 0;

( void )GEOSCoordSeq_getXY_r( geosctxt, nearestCoord.get(), 0, &nx, &ny );
#else
( void )GEOSCoordSeq_getX_r( geosctxt, nearestCoord.get(), 0, &nx );
Expand Down Expand Up @@ -855,6 +860,10 @@ void PointSet::getCentroid( double &px, double &py, bool forceInside ) const
{
const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, centroidGeom.get() );
#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
unsigned int nPoints = 0;
GEOSCoordSeq_getSize_r( geosctxt, coordSeq, &nPoints );
if ( nPoints == 0 )
return;
GEOSCoordSeq_getXY_r( geosctxt, coordSeq, 0, &px, &py );
#else
GEOSCoordSeq_getX_r( geosctxt, coordSeq, 0, &px );
Expand All @@ -871,6 +880,11 @@ void PointSet::getCentroid( double &px, double &py, bool forceInside ) const
{
const GEOSCoordSequence *coordSeq = GEOSGeom_getCoordSeq_r( geosctxt, pointGeom.get() );
#if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
unsigned int nPoints = 0;
GEOSCoordSeq_getSize_r( geosctxt, coordSeq, &nPoints );
if ( nPoints == 0 )
return;

GEOSCoordSeq_getXY_r( geosctxt, coordSeq, 0, &px, &py );
#else
GEOSCoordSeq_getX_r( geosctxt, coordSeq, 0, &px );
Expand Down
4 changes: 4 additions & 0 deletions tests/src/python/test_qgsgeometry.py
Expand Up @@ -5411,6 +5411,10 @@ def coerce_to_wkt(wkt, type):
self.assertEqual(coerce_to_wkt('MultiPolygon (((1 1, 1 2, 2 2, 1 1)),((3 3, 4 3, 4 4, 3 3)))',
QgsWkbTypes.MultiLineString), ['MultiLineString ((1 1, 1 2, 2 2, 1 1),(3 3, 4 3, 4 4, 3 3))'])

def testGeosCrash(self):
# test we don't crash when geos returns a point geometry with no points
QgsGeometry.fromWkt('Polygon ((0 0, 1 1, 1 0, 0 0))').intersection(QgsGeometry.fromWkt('Point (42 0)')).isNull()

def renderGeometry(self, geom, use_pen, as_polygon=False, as_painter_path=False):
image = QImage(200, 200, QImage.Format_RGB32)
image.fill(QColor(0, 0, 0))
Expand Down

0 comments on commit 5ae631a

Please sign in to comment.