Skip to content

Commit 452c806

Browse files
committedMay 11, 2017
Fix crash when transform errors occur while rendering
If a transform exception occurred while rendering a symbol then the QgsSymbolRenderContext cleanup code was never called, leading to a double delete and crash. Fixes #16377, #15345, and numerous other crashes seen "in the wild" Possibly refs #16385 (cherry-picked from fefa572)
1 parent bfa507a commit 452c806

File tree

1 file changed

+29
-3
lines changed

1 file changed

+29
-3
lines changed
 

‎src/core/symbology-ng/qgssymbolv2.cpp

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,27 @@ bool QgsSymbolV2::hasDataDefinedProperties() const
699699
return false;
700700
}
701701

702+
///@cond PRIVATE
703+
704+
/**
705+
* RAII class to pop scope from an expression context on destruction
706+
*/
707+
class ExpressionContextScopePopper
708+
{
709+
public:
710+
711+
ExpressionContextScopePopper() = default;
712+
713+
~ExpressionContextScopePopper()
714+
{
715+
if ( context )
716+
context->popScope();
717+
}
718+
719+
QgsExpressionContext *context = nullptr;
720+
};
721+
///@endcond PRIVATE
722+
702723
void QgsSymbolV2::renderFeature( const QgsFeature& feature, QgsRenderContext& context, int layer, bool selected, bool drawVertexMarker, int currentVertexMarkerType, int currentVertexMarkerSize )
703724
{
704725
const QgsGeometry* geom = feature.constGeometry();
@@ -728,9 +749,17 @@ void QgsSymbolV2::renderFeature( const QgsFeature& feature, QgsRenderContext& co
728749
mSymbolRenderContext->setGeometryPartCount( segmentizedGeometry->geometry()->partCount() );
729750
mSymbolRenderContext->setGeometryPartNum( 1 );
730751

752+
ExpressionContextScopePopper scopePopper;
731753
if ( mSymbolRenderContext->expressionContextScope() )
732754
{
755+
// this is somewhat nasty - by appending this scope here it's now owned
756+
// by both mSymbolRenderContext AND context.expressionContext()
757+
// the RAII scopePopper is required to make sure it always has ownership transferred back
758+
// from context.expressionContext(), even if exceptions of other early exits occur in this
759+
// function
733760
context.expressionContext().appendScope( mSymbolRenderContext->expressionContextScope() );
761+
scopePopper.context = &context.expressionContext();
762+
734763
QgsExpressionContextUtils::updateSymbolScope( this, mSymbolRenderContext->expressionContextScope() );
735764
mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_COUNT, mSymbolRenderContext->geometryPartCount(), true ) );
736765
mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_NUM, 1, true ) );
@@ -1011,9 +1040,6 @@ void QgsSymbolV2::renderFeature( const QgsFeature& feature, QgsRenderContext& co
10111040
{
10121041
delete segmentizedGeometry;
10131042
}
1014-
1015-
if ( mSymbolRenderContext->expressionContextScope() )
1016-
context.expressionContext().popScope();
10171043
}
10181044

10191045
QgsSymbolV2RenderContext* QgsSymbolV2::symbolRenderContext()

0 commit comments

Comments
 (0)
Please sign in to comment.