Skip to content

Commit 8243598

Browse files
committed
Even more memory safety for ogr layers
1 parent 6db46f7 commit 8243598

File tree

2 files changed

+51
-57
lines changed

2 files changed

+51
-57
lines changed

src/providers/ogr/qgsogrprovider.cpp

Lines changed: 25 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -192,18 +192,17 @@ void QgsOgrProvider::repack()
192192
{
193193
QgsMessageLog::logMessage( tr( "Possible corruption after REPACK detected. %1 still exists. This may point to a permission or locking problem of the original DBF." ).arg( packedDbf ), tr( "OGR" ), QgsMessageLog::CRITICAL );
194194
195-
if ( mOgrLayer != mOgrOrigLayer )
196-
QgsOgrProviderUtils::release( mOgrLayer );
197-
QgsOgrProviderUtils::release( mOgrOrigLayer );
195+
mOgrSqlLayer.reset();
196+
mOgrOrigLayer.reset();
198197
199198
QString errCause;
200199
if ( mLayerName.isNull() )
201200
{
202-
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, true, QStringList(), mLayerIndex, errCause ).release();
201+
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, true, QStringList(), mLayerIndex, errCause );
203202
}
204203
else
205204
{
206-
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, true, QStringList(), mLayerName, errCause ).release();
205+
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, true, QStringList(), mLayerName, errCause );
207206
}
208207
209208
if ( !mOgrOrigLayer )
@@ -212,7 +211,7 @@ void QgsOgrProvider::repack()
212211
mValid = false;
213212
}
214213
215-
mOgrLayer = mOgrOrigLayer;
214+
mOgrLayer = mOgrOrigLayer.get();
216215
}
217216
218217
}
@@ -526,17 +525,14 @@ bool QgsOgrProvider::setSubsetString( const QString &theSQL, bool updateFeatureC
526525
pushError( tr( "OGR[%1] error %2: %3" ).arg( CPLGetLastErrorType() ).arg( CPLGetLastErrorNo() ).arg( CPLGetLastErrorMsg() ) );
527526
return false;
528527
}
529-
QgsOgrLayerUniquePtr newLayer = QgsOgrProviderUtils::getSqlLayer( mOgrOrigLayer, subsetLayerH, theSQL );
530-
Q_ASSERT( newLayer );
531-
if ( mOgrLayer != mOgrOrigLayer )
532-
QgsOgrProviderUtils::release( mOgrLayer );
533-
mOgrLayer = newLayer.release();
528+
mOgrSqlLayer = QgsOgrProviderUtils::getSqlLayer( mOgrOrigLayer.get(), subsetLayerH, theSQL );
529+
Q_ASSERT( mOgrSqlLayer.get() );
530+
mOgrLayer = mOgrSqlLayer.get();
534531
}
535532
else
536533
{
537-
if ( mOgrLayer != mOgrOrigLayer )
538-
QgsOgrProviderUtils::release( mOgrLayer );
539-
mOgrLayer = mOgrOrigLayer;
534+
mOgrSqlLayer.reset();
535+
mOgrLayer = mOgrOrigLayer.get();
540536
}
541537
mSubsetString = theSQL;
542538

@@ -1138,7 +1134,7 @@ QgsRectangle QgsOgrProvider::extent() const
11381134
mExtent->MaxY = -std::numeric_limits<double>::max();
11391135

11401136
// TODO: This can be expensive, do we really need it!
1141-
if ( mOgrLayer == mOgrOrigLayer )
1137+
if ( mOgrLayer == mOgrOrigLayer.get() )
11421138
{
11431139
mOgrLayer->GetExtent( mExtent.get(), true );
11441140
}
@@ -1215,8 +1211,7 @@ size_t QgsOgrProvider::layerCount() const
12151211
if ( !mValid )
12161212
return 0;
12171213
return mOgrLayer->GetLayerCount();
1218-
} // QgsOgrProvider::layerCount()
1219-
1214+
}
12201215

12211216
/**
12221217
* Return the feature type
@@ -3787,7 +3782,7 @@ OGRLayerH QgsOgrProviderUtils::setSubsetString( OGRLayerH layer, GDALDatasetH ds
37873782
void QgsOgrProvider::open( OpenMode mode )
37883783
{
37893784
bool openReadOnly = false;
3790-
Q_ASSERT( !mOgrLayer );
3785+
Q_ASSERT( !mOgrSqlLayer );
37913786
Q_ASSERT( !mOgrOrigLayer );
37923787

37933788
// Try to open using VSIFileHandler
@@ -3836,11 +3831,11 @@ void QgsOgrProvider::open( OpenMode mode )
38363831
// has precedence over the layerid if both are given.
38373832
if ( !mLayerName.isNull() )
38383833
{
3839-
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, true, options, mLayerName, errCause ).release();
3834+
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, true, options, mLayerName, errCause );
38403835
}
38413836
else
38423837
{
3843-
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, true, options, mLayerIndex, errCause ).release();
3838+
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, true, options, mLayerIndex, errCause );
38443839
}
38453840
}
38463841

@@ -3861,11 +3856,11 @@ void QgsOgrProvider::open( OpenMode mode )
38613856
// try to open read-only
38623857
if ( !mLayerName.isNull() )
38633858
{
3864-
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, false, QStringList(), mLayerName, errCause ).release();
3859+
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, false, QStringList(), mLayerName, errCause );
38653860
}
38663861
else
38673862
{
3868-
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, false, QStringList(), mLayerIndex, errCause ).release();
3863+
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, false, QStringList(), mLayerIndex, errCause );
38693864
}
38703865
}
38713866

@@ -3875,7 +3870,7 @@ void QgsOgrProvider::open( OpenMode mode )
38753870

38763871
QgsDebugMsg( "OGR opened using Driver " + mGDALDriverName );
38773872

3878-
mOgrLayer = mOgrOrigLayer;
3873+
mOgrLayer = mOgrOrigLayer.get();
38793874

38803875
// check that the initial encoding setting is fit for this layer
38813876
setEncoding( encoding() );
@@ -3912,8 +3907,8 @@ void QgsOgrProvider::open( OpenMode mode )
39123907
if ( mValid && mode == OpenModeInitial && mWriteAccess &&
39133908
( mGDALDriverName == QLatin1String( "ESRI Shapefile" ) || mGDALDriverName == QLatin1String( "MapInfo File" ) ) )
39143909
{
3915-
QgsOgrProviderUtils::release( mOgrOrigLayer );
3916-
mOgrLayer = mOgrOrigLayer = nullptr;
3910+
mOgrOrigLayer.reset();
3911+
mOgrLayer = nullptr;
39173912
mValid = false;
39183913

39193914
// In the case where we deal with a shapefile, it is possible that it has
@@ -3929,15 +3924,15 @@ void QgsOgrProvider::open( OpenMode mode )
39293924
// try to open read-only
39303925
if ( !mLayerName.isNull() )
39313926
{
3932-
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, false, QStringList(), mLayerName, errCause ).release();
3927+
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, false, QStringList(), mLayerName, errCause );
39333928
}
39343929
else
39353930
{
3936-
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, false, QStringList(), mLayerIndex, errCause ).release();
3931+
mOgrOrigLayer = QgsOgrProviderUtils::getLayer( mFilePath, false, QStringList(), mLayerIndex, errCause );
39373932
}
39383933

39393934
mWriteAccess = false;
3940-
mOgrLayer = mOgrOrigLayer;
3935+
mOgrLayer = mOgrOrigLayer.get();
39413936
if ( mOgrLayer )
39423937
{
39433938
mValid = true;
@@ -3964,14 +3959,9 @@ void QgsOgrProvider::open( OpenMode mode )
39643959

39653960
void QgsOgrProvider::close()
39663961
{
3967-
if ( mOgrLayer != mOgrOrigLayer )
3968-
{
3969-
QgsOgrProviderUtils::release( mOgrLayer );
3970-
}
3971-
3972-
QgsOgrProviderUtils::release( mOgrOrigLayer );
3962+
mOgrSqlLayer.reset();
3963+
mOgrOrigLayer.reset();
39733964
mOgrLayer = nullptr;
3974-
mOgrOrigLayer = nullptr;
39753965
mValid = false;
39763966
setProperty( "_debug_open_mode", "invalid" );
39773967

src/providers/ogr/qgsogrprovider.h

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,24 @@ class QgsOgrFeatureIterator;
3434

3535
class QgsOgrLayer;
3636

37+
/**
38+
* Releases a QgsOgrLayer
39+
*/
40+
struct QgsOgrLayerReleaser
41+
{
42+
43+
/**
44+
* Releases a QgsOgrLayer \a layer.
45+
*/
46+
void operator()( QgsOgrLayer *layer );
47+
48+
};
49+
50+
/**
51+
* Scoped QgsOgrLayer.
52+
*/
53+
using QgsOgrLayerUniquePtr = std::unique_ptr< QgsOgrLayer, QgsOgrLayerReleaser>;
54+
3755
/**
3856
\class QgsOgrProvider
3957
\brief Data provider for OGR datasources
@@ -206,11 +224,17 @@ class QgsOgrProvider : public QgsVectorDataProvider
206224
in the method QgsOgrProvider::extent(). The purpose is to prevent a memory leak*/
207225
mutable QgsRectangle mExtentRect;
208226

209-
//! Current working layer (might be a SQL result layer if mSubsetString is set)
227+
/**
228+
* Current working layer - will point to either mOgrSqlLayer or mOgrOrigLayer depending
229+
* on whether a subset string is set
230+
*/
210231
QgsOgrLayer *mOgrLayer = nullptr;
211232

233+
//! SQL result layer, used if a subset string is set
234+
QgsOgrLayerUniquePtr mOgrSqlLayer;
235+
212236
//! Original layer (not a SQL result layer)
213-
QgsOgrLayer *mOgrOrigLayer = nullptr;
237+
QgsOgrLayerUniquePtr mOgrOrigLayer;
214238

215239
//! path to filename
216240
QString mFilePath;
@@ -285,26 +309,6 @@ class QgsOgrProvider : public QgsVectorDataProvider
285309

286310
};
287311

288-
class QgsOgrLayer;
289-
290-
/**
291-
* Releases a QgsOgrLayer
292-
*/
293-
struct QgsOgrLayerReleaser
294-
{
295-
296-
/**
297-
* Releases a QgsOgrLayer \a layer.
298-
*/
299-
void operator()( QgsOgrLayer *layer );
300-
301-
};
302-
303-
/**
304-
* Scoped QgsOgrLayer.
305-
*/
306-
using QgsOgrLayerUniquePtr = std::unique_ptr< QgsOgrLayer, QgsOgrLayerReleaser>;
307-
308312
/**
309313
\class QgsOgrProviderUtils
310314
\brief Utility class with static methods

0 commit comments

Comments
 (0)