Abhilash Raj pushed to branch master at GNU Mailman / Mailman Core


Commits:
757e940a by Abhilash Raj at 2022-01-29T04:38:27+00:00
Fix a bug where exception in plugin initialization can cause crash.

- - - - -
4564222d by Abhilash Raj at 2022-01-29T04:38:27+00:00
Merge branch 'fix-500' into 'master'

Fix a bug where exception in plugin initialization can cause crash.

See merge request mailman/mailman!952
- - - - -


3 changed files:

- src/mailman/core/initialize.py
- src/mailman/docs/NEWS.rst
- src/mailman/plugins/tests/test_plugins.py


Changes:

=====================================
src/mailman/core/initialize.py
=====================================
@@ -130,6 +130,27 @@ def initialize_1(config_path=None):
         mailman.config.config.push('extra testing config', extra_cfg)
 
 
+@public
+def run_plugin_pre_hook(config):
+    """Run the plugin pre_hooks, if one fails, disable the offending plugin."""
+    disabled_plugins = []
+    for name in config.plugins:                     # pragma: nocover
+        plugin = config.plugins[name]
+        if hasattr(plugin, 'pre_hook'):
+            try:
+                plugin.pre_hook()
+            except Exception:                                # pragma: nocover
+                log = logging.getLogger('mailman.plugins')
+                log.exception('Plugin failed to run its pre_hook: "{}". '
+                              'It will be disabled and its components '
+                              "won't be loaded.".format(name))
+                disabled_plugins.append(name)
+
+    if disabled_plugins:
+        for plugin in disabled_plugins:
+            del config.plugins[plugin]
+
+
 @public
 def initialize_2(debug=False, propagate_logs=None, testing=False):
     """Second initialization step.
@@ -159,18 +180,7 @@ def initialize_2(debug=False, propagate_logs=None, 
testing=False):
         log.warning(
             'The [mailman]pre_hook configuration value has been replaced '
             "by the plugins infrastructure, and won't be called.")
-    # Run the plugin pre_hooks, if one fails, disable the offending plugin.
-    for name in config.plugins:                     # pragma: nocover
-        plugin = config.plugins[name]
-        if hasattr(plugin, 'pre_hook'):
-            try:
-                plugin.pre_hook()
-            except Exception:                                # pragma: nocover
-                log = logging.getLogger('mailman.plugins')
-                log.exception('Plugin failed to run its pre_hook: {}'
-                              'It will be disabled and its components '
-                              "won't be loaded.".format(name))
-                del config.plugins[name]
+    run_plugin_pre_hook(config)
     # Instantiate the database class, ensure that it's of the right type, and
     # initialize it.  Then stash the object on our configuration object.
     utility_name = ('testing' if testing else 'production')


=====================================
src/mailman/docs/NEWS.rst
=====================================
@@ -31,6 +31,9 @@ Bugs fixed
   contained non-ascii.  This is fixed.  (Closes #965 and #967)
 * The REST API will now accept JSON encoded data with boolean values for
   boolean attributes.  (Closes #970)
+* Fix a bug where loading a plugin which raises an exception in ``pre_hook``
+  can cause Mailman to crash trying to disable that plugin. (Closes #724)
+  
 
 .. _news-3.3.5:
 


=====================================
src/mailman/plugins/tests/test_plugins.py
=====================================
@@ -21,6 +21,7 @@ import sys
 import unittest
 
 from contextlib import ExitStack
+from mailman.core.initialize import run_plugin_pre_hook
 from mailman.interfaces.plugin import IPlugin
 from mailman.plugins.initialize import initialize
 from mailman.plugins.testing.layer import PluginRESTLayer
@@ -53,6 +54,16 @@ class TestablePlugin:
     resource = None
 
 
+@implementer(IPlugin)
+class ExceptionRaisingPlugin:
+    def pre_hook(self):
+        raise Exception('Bad plugin')
+
+    def post_hook(self):
+        pass
+    resource = None
+
+
 class TestInitializePlugins(unittest.TestCase):
     layer = ConfigLayer
 
@@ -144,3 +155,23 @@ class TestInitializePlugins(unittest.TestCase):
             initialize()
             log_mock.info.assert_called_once_with(
                 'Plugin not enabled, or empty class path: example')
+
+    def test_plugin_disabled_with_exception(self):
+        with ExitStack() as resources:
+            system_path = resources.enter_context(TemporaryDirectory())
+            fake_plugin_config = {
+                'path': system_path,
+                'enabled': 'yes',
+                'class': 'ExamplePlugin',
+                }
+            testable_plugin = ExceptionRaisingPlugin()
+            fake_mailman_config = SimpleNamespace(
+                plugin_configs=[('example', fake_plugin_config)],
+                plugins={'example': testable_plugin},
+                )
+
+            resources.enter_context(patch(
+                'mailman.plugins.initialize.call_name',
+                return_value=testable_plugin))
+            run_plugin_pre_hook(fake_mailman_config)
+            self.assertNotIn('example', fake_mailman_config.plugins)



View it on GitLab: 
https://gitlab.com/mailman/mailman/-/compare/b0dd5d62c3225fbd1db1894d3a04be9facf11e06...4564222d71a241375abfc201224ee03ef4ca0949

-- 
View it on GitLab: 
https://gitlab.com/mailman/mailman/-/compare/b0dd5d62c3225fbd1db1894d3a04be9facf11e06...4564222d71a241375abfc201224ee03ef4ca0949
You're receiving this email because of your account on gitlab.com.


_______________________________________________
Mailman-checkins mailing list -- mailman-checkins@python.org
To unsubscribe send an email to mailman-checkins-le...@python.org
https://mail.python.org/mailman3/lists/mailman-checkins.python.org/
Member address: arch...@jab.org

Reply via email to