Skip to content

Commit

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

for a point geometry

Fixes #35719, fixes #35526
  • Loading branch information
nyalldawson committed Apr 15, 2020
1 parent 8c488b4 commit 774f1db
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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 774f1db

Please sign in to comment.