Skip to content

Commit d313405

Browse files
committed
Avoid working on reference to temporary objects
fixes a couple of crashes in geometry validation
1 parent 7d83263 commit d313405

File tree

7 files changed

+32
-23
lines changed

7 files changed

+32
-23
lines changed

python/analysis/auto_generated/vector/geometry_checker/qgsgeometrycheckerutils.sip.in

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ If ``useMapCrs`` is ``True``, geometries will be reprojected to the mapCrs defin
5151
in ``context``.
5252
%End
5353

54-
const QgsFeature &feature() const;
54+
QgsFeature feature() const;
5555
%Docstring
5656
Returns the feature.
5757
The geometry will not be reprojected regardless of useMapCrs.
@@ -63,7 +63,7 @@ The geometry will not be reprojected regardless of useMapCrs.
6363
The layer id.
6464
%End
6565

66-
const QgsGeometry &geometry() const;
66+
QgsGeometry geometry() const;
6767
%Docstring
6868
Returns the geometry of this feature.
6969
If useMapCrs was specified, it will already be reprojected into the

src/analysis/vector/geometry_checker/qgsgeometrycheckerutils.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ QgsGeometryCheckerUtils::LayerFeature::LayerFeature( const QgsFeaturePool *pool,
5252
}
5353
}
5454

55-
const QgsFeature &QgsGeometryCheckerUtils::LayerFeature::feature() const
55+
QgsFeature QgsGeometryCheckerUtils::LayerFeature::feature() const
5656
{
5757
return mFeature;
5858
}
@@ -67,7 +67,7 @@ QString QgsGeometryCheckerUtils::LayerFeature::layerId() const
6767
return mFeaturePool->layerId();
6868
}
6969

70-
const QgsGeometry &QgsGeometryCheckerUtils::LayerFeature::geometry() const
70+
QgsGeometry QgsGeometryCheckerUtils::LayerFeature::geometry() const
7171
{
7272
return mGeometry;
7373
}

src/analysis/vector/geometry_checker/qgsgeometrycheckerutils.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class ANALYSIS_EXPORT QgsGeometryCheckerUtils
6464
* Returns the feature.
6565
* The geometry will not be reprojected regardless of useMapCrs.
6666
*/
67-
const QgsFeature &feature() const;
67+
QgsFeature feature() const;
6868

6969
/**
7070
* The layer.
@@ -81,7 +81,7 @@ class ANALYSIS_EXPORT QgsGeometryCheckerUtils
8181
* If useMapCrs was specified, it will already be reprojected into the
8282
* CRS specified in the context specified in the constructor.
8383
*/
84-
const QgsGeometry &geometry() const;
84+
QgsGeometry geometry() const;
8585

8686
/**
8787
* Returns a combination of the layerId and the feature id.

src/analysis/vector/geometry_checker/qgsgeometrygapcheck.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,11 @@ void QgsGeometryGapCheck::collectErrors( const QMap<QString, QgsFeaturePool *> &
115115
const QgsGeometryCheckerUtils::LayerFeatures layerFeatures( featurePools, featureIds.keys(), gapAreaBBox, compatibleGeometryTypes(), mContext );
116116
for ( const QgsGeometryCheckerUtils::LayerFeature &layerFeature : layerFeatures )
117117
{
118-
if ( QgsGeometryCheckerUtils::sharedEdgeLength( gapGeom.get(), layerFeature.geometry().constGet(), mContext->reducedTolerance ) > 0 )
118+
const QgsGeometry geom = layerFeature.geometry();
119+
if ( QgsGeometryCheckerUtils::sharedEdgeLength( gapGeom.get(), geom.constGet(), mContext->reducedTolerance ) > 0 )
119120
{
120121
neighboringIds[layerFeature.layer()->id()].insert( layerFeature.feature().id() );
121-
gapAreaBBox.combineExtentWith( layerFeature.geometry().constGet()->boundingBox() );
122+
gapAreaBBox.combineExtentWith( layerFeature.geometry().boundingBox() );
122123
}
123124
}
124125

@@ -193,7 +194,7 @@ bool QgsGeometryGapCheck::mergeWithNeighbor( const QMap<QString, QgsFeaturePool
193194
{
194195
continue;
195196
}
196-
QgsGeometry featureGeom = testFeature.geometry();
197+
const QgsGeometry featureGeom = testFeature.geometry();
197198
const QgsAbstractGeometry *testGeom = featureGeom.constGet();
198199
for ( int iPart = 0, nParts = testGeom->partCount(); iPart < nParts; ++iPart )
199200
{
@@ -219,7 +220,7 @@ bool QgsGeometryGapCheck::mergeWithNeighbor( const QMap<QString, QgsFeaturePool
219220
std::unique_ptr<QgsAbstractGeometry> errLayerGeom( errGeometry->clone() );
220221
QgsCoordinateTransform ct( featurePool->crs(), mContext->mapCrs, mContext->transformContext );
221222
errLayerGeom->transform( ct, QgsCoordinateTransform::ReverseTransform );
222-
QgsGeometry mergeFeatureGeom = mergeFeature.geometry();
223+
const QgsGeometry mergeFeatureGeom = mergeFeature.geometry();
223224
const QgsAbstractGeometry *mergeGeom = mergeFeatureGeom.constGet();
224225
std::unique_ptr< QgsGeometryEngine > geomEngine = QgsGeometryCheckerUtils::createGeomEngine( errLayerGeom.get(), mContext->reducedTolerance );
225226
std::unique_ptr<QgsAbstractGeometry> combinedGeom( geomEngine->combine( QgsGeometryCheckerUtils::getGeomPart( mergeGeom, mergePartIdx ), &errMsg ) );

src/analysis/vector/geometry_checker/qgsgeometrylinelayerintersectioncheck.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ void QgsGeometryLineLayerIntersectionCheck::collectErrors( const QMap<QString, Q
5757
}
5858
else if ( const QgsPolygon *polygon = dynamic_cast<const QgsPolygon *>( part ) )
5959
{
60-
QList< const QgsLineString * > rings = QgsGeometryCheckerUtils::polygonRings( polygon );
60+
const QList< const QgsLineString * > rings = QgsGeometryCheckerUtils::polygonRings( polygon );
6161
for ( const QgsLineString *ring : rings )
6262
{
6363
const QList< QgsPoint > intersections = QgsGeometryCheckerUtils::lineIntersections( line, ring, mContext->tolerance );

src/analysis/vector/geometry_checker/qgsgeometrymissingvertexcheck.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ void QgsGeometryMissingVertexCheck::collectErrors( const QMap<QString, QgsFeatur
4848
break;
4949
}
5050

51-
const QgsAbstractGeometry *geom = layerFeature.geometry().constGet();
51+
const QgsGeometry geometry = layerFeature.geometry();
52+
const QgsAbstractGeometry *geom = geometry.constGet();
5253

5354
if ( QgsCurvePolygon *polygon = qgsgeometry_cast<QgsCurvePolygon *>( geom ) )
5455
{
@@ -129,7 +130,7 @@ void QgsGeometryMissingVertexCheck::processPolygon( const QgsCurvePolygon *polyg
129130
const QgsFeature &currentFeature = layerFeature.feature();
130131
std::unique_ptr<QgsMultiPolygon> boundaries = qgis::make_unique<QgsMultiPolygon>();
131132

132-
std::unique_ptr< QgsGeometryEngine > geomEngine = QgsGeometryCheckerUtils::createGeomEngine( polygon->exteriorRing(), mContext->tolerance );
133+
std::unique_ptr< QgsGeometryEngine > geomEngine = QgsGeometryCheckerUtils::createGeomEngine( polygon->exteriorRing()->clone(), mContext->tolerance );
133134
boundaries->addGeometry( geomEngine->buffer( mContext->tolerance, 5 ) );
134135

135136
const int numRings = polygon->numInteriorRings();
@@ -155,7 +156,8 @@ void QgsGeometryMissingVertexCheck::processPolygon( const QgsCurvePolygon *polyg
155156
if ( feedback && feedback->isCanceled() )
156157
break;
157158

158-
QgsVertexIterator vertexIterator = compareFeature.geometry().vertices();
159+
const QgsGeometry compareGeometry = compareFeature.geometry();
160+
QgsVertexIterator vertexIterator = compareGeometry.vertices();
159161
while ( vertexIterator.hasNext() )
160162
{
161163
const QgsPoint &pt = vertexIterator.next();

src/analysis/vector/geometry_checker/qgsgeometryoverlapcheck.cpp

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ void QgsGeometryOverlapCheck::collectErrors( const QMap<QString, QgsFeaturePool
4141
// Ensure each pair of layers only gets compared once: remove the current layer from the layerIds, but add it to the layerList for layerFeaturesB
4242
layerIds.removeOne( layerFeatureA.layer()->id() );
4343

44-
QgsRectangle bboxA = layerFeatureA.geometry().constGet()->boundingBox();
45-
std::unique_ptr< QgsGeometryEngine > geomEngineA = QgsGeometryCheckerUtils::createGeomEngine( layerFeatureA.geometry().constGet(), mContext->tolerance );
44+
const QgsGeometry geomA = layerFeatureA.geometry();
45+
QgsRectangle bboxA = geomA.boundingBox();
46+
std::unique_ptr< QgsGeometryEngine > geomEngineA = QgsGeometryCheckerUtils::createGeomEngine( geomA.constGet(), mContext->tolerance );
47+
geomEngineA->prepareGeometry();
4648
if ( !geomEngineA->isValid() )
4749
{
4850
messages.append( tr( "Overlap check failed for (%1): the geometry is invalid" ).arg( layerFeatureA.id() ) );
@@ -56,14 +58,16 @@ void QgsGeometryOverlapCheck::collectErrors( const QMap<QString, QgsFeaturePool
5658
break;
5759

5860
// > : only report overlaps within same layer once
59-
if ( layerFeatureA.layer()->id() == layerFeatureB.layer()->id() && layerFeatureB.feature().id() >= layerFeatureA.feature().id() )
61+
if ( layerFeatureA.layerId() == layerFeatureB.layerId() && layerFeatureB.feature().id() >= layerFeatureA.feature().id() )
6062
{
6163
continue;
6264
}
6365
QString errMsg;
64-
if ( geomEngineA->overlaps( layerFeatureB.geometry().constGet(), &errMsg ) )
66+
const QgsGeometry geometryB = layerFeatureB.geometry();
67+
const QgsAbstractGeometry *geomB = geometryB.constGet();
68+
if ( geomEngineA->overlaps( geomB, &errMsg ) )
6569
{
66-
std::unique_ptr<QgsAbstractGeometry> interGeom( geomEngineA->intersection( layerFeatureB.geometry().constGet() ) );
70+
std::unique_ptr<QgsAbstractGeometry> interGeom( geomEngineA->intersection( geomB ) );
6771
if ( interGeom && !interGeom->isEmpty() )
6872
{
6973
QgsGeometryCheckerUtils::filter1DTypes( interGeom.get() );
@@ -105,14 +109,16 @@ void QgsGeometryOverlapCheck::fixError( const QMap<QString, QgsFeaturePool *> &f
105109
// Check if error still applies
106110
QgsGeometryCheckerUtils::LayerFeature layerFeatureA( featurePoolA, featureA, mContext, true );
107111
QgsGeometryCheckerUtils::LayerFeature layerFeatureB( featurePoolB, featureB, mContext, true );
108-
std::unique_ptr< QgsGeometryEngine > geomEngineA = QgsGeometryCheckerUtils::createGeomEngine( layerFeatureA.geometry().constGet(), mContext->reducedTolerance );
112+
const QgsGeometry geometryA = layerFeatureA.geometry();
113+
std::unique_ptr< QgsGeometryEngine > geomEngineA = QgsGeometryCheckerUtils::createGeomEngine( geometryA.constGet(), mContext->reducedTolerance );
109114

110-
if ( !geomEngineA->overlaps( layerFeatureB.geometry().constGet() ) )
115+
const QgsGeometry geometryB = layerFeatureB.geometry();
116+
if ( !geomEngineA->overlaps( geometryB.constGet() ) )
111117
{
112118
error->setObsolete();
113119
return;
114120
}
115-
std::unique_ptr< QgsAbstractGeometry > interGeom( geomEngineA->intersection( layerFeatureB.geometry().constGet(), &errMsg ) );
121+
std::unique_ptr< QgsAbstractGeometry > interGeom( geomEngineA->intersection( geometryB.constGet(), &errMsg ) );
116122
if ( !interGeom )
117123
{
118124
error->setFixFailed( tr( "Failed to compute intersection between overlapping features: %1" ).arg( errMsg ) );
@@ -153,7 +159,7 @@ void QgsGeometryOverlapCheck::fixError( const QMap<QString, QgsFeaturePool *> &f
153159
{
154160
QgsGeometryCheckerUtils::filter1DTypes( diff1.get() );
155161
}
156-
std::unique_ptr< QgsGeometryEngine > geomEngineB = QgsGeometryCheckerUtils::createGeomEngine( layerFeatureB.geometry().constGet(), mContext->reducedTolerance );
162+
std::unique_ptr< QgsGeometryEngine > geomEngineB = QgsGeometryCheckerUtils::createGeomEngine( geometryB.constGet(), mContext->reducedTolerance );
157163
std::unique_ptr< QgsAbstractGeometry > diff2( geomEngineB->difference( interPart, &errMsg ) );
158164
if ( !diff2 || diff2->isEmpty() )
159165
{

0 commit comments

Comments
 (0)