Skip to content

Commit 8db38af

Browse files
committed
Processing: fix crash in alg runner task with bad scripts
Fixes #21270 With test
1 parent 377040a commit 8db38af

File tree

4 files changed

+103
-1
lines changed

4 files changed

+103
-1
lines changed

src/core/processing/qgsprocessingalgorithm.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ QgsProcessingAlgorithm::~QgsProcessingAlgorithm()
4040
QgsProcessingAlgorithm *QgsProcessingAlgorithm::create( const QVariantMap &configuration ) const
4141
{
4242
std::unique_ptr< QgsProcessingAlgorithm > creation( createInstance() );
43+
if ( ! creation )
44+
throw QgsProcessingException( QObject::tr( "Error creating algorithm from createInstance()" ) );
4345
creation->setProvider( provider() );
4446
creation->initAlgorithm( configuration );
4547
return creation.release();

src/core/processing/qgsprocessingalgrunnertask.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ QgsProcessingAlgRunnerTask::QgsProcessingAlgRunnerTask( const QgsProcessingAlgor
3434
mOwnedFeedback.reset( new QgsProcessingFeedback() );
3535
mFeedback = mOwnedFeedback.get();
3636
}
37-
if ( !mAlgorithm->prepare( mParameters, context, mFeedback ) )
37+
if ( !( mAlgorithm && mAlgorithm->prepare( mParameters, context, mFeedback ) ) )
3838
cancel();
3939
}
4040

tests/src/python/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ ADD_PYTHON_TEST(PyQgsPointDisplacementRenderer test_qgspointdisplacementrenderer
154154
ADD_PYTHON_TEST(PyQgsPostgresDomain test_qgspostgresdomain.py)
155155
ADD_PYTHON_TEST(PyQgsProcessingRecentAlgorithmLog test_qgsprocessingrecentalgorithmslog.py)
156156
ADD_PYTHON_TEST(PyQgsProcessingInPlace test_qgsprocessinginplace.py)
157+
ADD_PYTHON_TEST(PyQgsProcessingAlgRunner test_qgsprocessingalgrunner.py)
157158
ADD_PYTHON_TEST(PyQgsProcessingAlgDecorator test_processing_alg_decorator.py)
158159
ADD_PYTHON_TEST(PyQgsProjectionSelectionWidgets test_qgsprojectionselectionwidgets.py)
159160
ADD_PYTHON_TEST(PyQgsProjectMetadata test_qgsprojectmetadata.py)
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# -*- coding: utf-8 -*-
2+
"""QGIS Unit tests for Processing algorithm runner(s).
3+
4+
.. note:: This program is free software; you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation; either version 2 of the License, or
7+
(at your option) any later version.
8+
"""
9+
__author__ = 'Alessandro Pasotti'
10+
__date__ = '2019-02'
11+
__copyright__ = 'Copyright 2019, The QGIS Project'
12+
# This will get replaced with a git SHA1 when you do a git archive
13+
__revision__ = '$Format:%H$'
14+
15+
import re
16+
from qgis.PyQt.QtCore import QCoreApplication
17+
from qgis.testing import start_app, unittest
18+
from qgis.core import QgsProcessingAlgRunnerTask
19+
20+
from processing.core.Processing import Processing
21+
from processing.core.ProcessingConfig import ProcessingConfig
22+
from qgis.testing import start_app, unittest
23+
from qgis.analysis import QgsNativeAlgorithms
24+
from qgis.core import (
25+
QgsApplication,
26+
QgsSettings,
27+
QgsProcessingContext,
28+
QgsProcessingAlgRunnerTask,
29+
QgsProcessingAlgorithm,
30+
QgsProject,
31+
)
32+
33+
start_app()
34+
35+
36+
class CrashingProcessingAlgorithm(QgsProcessingAlgorithm):
37+
"""
38+
Wrong class in factory createInstance()
39+
"""
40+
41+
INPUT = 'INPUT'
42+
OUTPUT = 'OUTPUT'
43+
44+
def tr(self, string):
45+
return QCoreApplication.translate('Processing', string)
46+
47+
def createInstance(self):
48+
"""Wrong!"""
49+
return ExampleProcessingAlgorithm()
50+
51+
def name(self):
52+
return 'mycrashingscript'
53+
54+
def displayName(self):
55+
return self.tr('My Crashing Script')
56+
57+
def group(self):
58+
return self.tr('Example scripts')
59+
60+
def groupId(self):
61+
return 'examplescripts'
62+
63+
def shortHelpString(self):
64+
return self.tr("Example algorithm short description")
65+
66+
def initAlgorithm(self, config=None):
67+
pass
68+
69+
def processAlgorithm(self, parameters, context, feedback):
70+
return {self.OUTPUT: 'an_id'}
71+
72+
73+
class TestQgsProcessingAlgRunner(unittest.TestCase):
74+
75+
@classmethod
76+
def setUpClass(cls):
77+
"""Run before all tests"""
78+
QCoreApplication.setOrganizationName("QGIS_Test")
79+
QCoreApplication.setOrganizationDomain(
80+
"QGIS_TestPyQgsProcessingInPlace.com")
81+
QCoreApplication.setApplicationName("QGIS_TestPyQgsProcessingInPlace")
82+
QgsSettings().clear()
83+
Processing.initialize()
84+
QgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms())
85+
cls.registry = QgsApplication.instance().processingRegistry()
86+
87+
def test_bad_script_dont_crash(self):
88+
"""Test regression #21270 (segfault)"""
89+
90+
context = QgsProcessingContext()
91+
context.setProject(QgsProject.instance())
92+
with self.assertRaises(Exception) as e:
93+
QgsProcessingAlgRunnerTask(CrashingProcessingAlgorithm(), {}, context=context)
94+
95+
self.assertEqual(str(e.exception), 'unknown')
96+
97+
98+
if __name__ == '__main__':
99+
unittest.main()

0 commit comments

Comments
 (0)