Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Processing: fix crash in alg runner task with bad scripts
Fixes #21270

With test
  • Loading branch information
elpaso committed Feb 18, 2019
1 parent 377040a commit 8db38af
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/core/processing/qgsprocessingalgorithm.cpp
Expand Up @@ -40,6 +40,8 @@ QgsProcessingAlgorithm::~QgsProcessingAlgorithm()
QgsProcessingAlgorithm *QgsProcessingAlgorithm::create( const QVariantMap &configuration ) const
{
std::unique_ptr< QgsProcessingAlgorithm > creation( createInstance() );
if ( ! creation )
throw QgsProcessingException( QObject::tr( "Error creating algorithm from createInstance()" ) );
creation->setProvider( provider() );
creation->initAlgorithm( configuration );
return creation.release();
Expand Down
2 changes: 1 addition & 1 deletion src/core/processing/qgsprocessingalgrunnertask.cpp
Expand Up @@ -34,7 +34,7 @@ QgsProcessingAlgRunnerTask::QgsProcessingAlgRunnerTask( const QgsProcessingAlgor
mOwnedFeedback.reset( new QgsProcessingFeedback() );
mFeedback = mOwnedFeedback.get();
}
if ( !mAlgorithm->prepare( mParameters, context, mFeedback ) )
if ( !( mAlgorithm && mAlgorithm->prepare( mParameters, context, mFeedback ) ) )
cancel();
}

Expand Down
1 change: 1 addition & 0 deletions tests/src/python/CMakeLists.txt
Expand Up @@ -154,6 +154,7 @@ ADD_PYTHON_TEST(PyQgsPointDisplacementRenderer test_qgspointdisplacementrenderer
ADD_PYTHON_TEST(PyQgsPostgresDomain test_qgspostgresdomain.py)
ADD_PYTHON_TEST(PyQgsProcessingRecentAlgorithmLog test_qgsprocessingrecentalgorithmslog.py)
ADD_PYTHON_TEST(PyQgsProcessingInPlace test_qgsprocessinginplace.py)
ADD_PYTHON_TEST(PyQgsProcessingAlgRunner test_qgsprocessingalgrunner.py)
ADD_PYTHON_TEST(PyQgsProcessingAlgDecorator test_processing_alg_decorator.py)
ADD_PYTHON_TEST(PyQgsProjectionSelectionWidgets test_qgsprojectionselectionwidgets.py)
ADD_PYTHON_TEST(PyQgsProjectMetadata test_qgsprojectmetadata.py)
Expand Down
99 changes: 99 additions & 0 deletions tests/src/python/test_qgsprocessingalgrunner.py
@@ -0,0 +1,99 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for Processing algorithm runner(s).
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
"""
__author__ = 'Alessandro Pasotti'
__date__ = '2019-02'
__copyright__ = 'Copyright 2019, The QGIS Project'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'

import re
from qgis.PyQt.QtCore import QCoreApplication
from qgis.testing import start_app, unittest
from qgis.core import QgsProcessingAlgRunnerTask

from processing.core.Processing import Processing
from processing.core.ProcessingConfig import ProcessingConfig
from qgis.testing import start_app, unittest
from qgis.analysis import QgsNativeAlgorithms
from qgis.core import (
QgsApplication,
QgsSettings,
QgsProcessingContext,
QgsProcessingAlgRunnerTask,
QgsProcessingAlgorithm,
QgsProject,
)

start_app()


class CrashingProcessingAlgorithm(QgsProcessingAlgorithm):
"""
Wrong class in factory createInstance()
"""

INPUT = 'INPUT'
OUTPUT = 'OUTPUT'

def tr(self, string):
return QCoreApplication.translate('Processing', string)

def createInstance(self):
"""Wrong!"""
return ExampleProcessingAlgorithm()

def name(self):
return 'mycrashingscript'

def displayName(self):
return self.tr('My Crashing Script')

def group(self):
return self.tr('Example scripts')

def groupId(self):
return 'examplescripts'

def shortHelpString(self):
return self.tr("Example algorithm short description")

def initAlgorithm(self, config=None):
pass

def processAlgorithm(self, parameters, context, feedback):
return {self.OUTPUT: 'an_id'}


class TestQgsProcessingAlgRunner(unittest.TestCase):

@classmethod
def setUpClass(cls):
"""Run before all tests"""
QCoreApplication.setOrganizationName("QGIS_Test")
QCoreApplication.setOrganizationDomain(
"QGIS_TestPyQgsProcessingInPlace.com")
QCoreApplication.setApplicationName("QGIS_TestPyQgsProcessingInPlace")
QgsSettings().clear()
Processing.initialize()
QgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms())
cls.registry = QgsApplication.instance().processingRegistry()

def test_bad_script_dont_crash(self):
"""Test regression #21270 (segfault)"""

context = QgsProcessingContext()
context.setProject(QgsProject.instance())
with self.assertRaises(Exception) as e:
QgsProcessingAlgRunnerTask(CrashingProcessingAlgorithm(), {}, context=context)

self.assertEqual(str(e.exception), 'unknown')


if __name__ == '__main__':
unittest.main()

0 comments on commit 8db38af

Please sign in to comment.