Skip to content

Commit

Permalink
Merge pull request #1579 from asottile/forbid-invalid-plugin-codes
Browse files Browse the repository at this point in the history
forbid invalid plugin prefixes in plugin loading
  • Loading branch information
asottile committed Apr 11, 2022
2 parents 3ce7615 + f3443f4 commit 7e1e8b3
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 0 deletions.
11 changes: 11 additions & 0 deletions src/flake8/plugins/finder.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""Functions related to finding and loading plugins."""
import configparser
import inspect
import itertools
import logging
import re
import sys
from typing import Any
from typing import Dict
Expand All @@ -20,6 +22,8 @@

LOG = logging.getLogger(__name__)

VALID_CODE = re.compile("^[A-Z]{1,3}[0-9]{0,3}$", re.ASCII)

FLAKE8_GROUPS = frozenset(("flake8.extension", "flake8.report"))

BANNED_PLUGINS = {
Expand Down Expand Up @@ -328,6 +332,13 @@ def _classify_plugins(
else:
raise NotImplementedError(f"what plugin type? {loaded}")

for loaded in itertools.chain(tree, logical_line, physical_line):
if not VALID_CODE.match(loaded.entry_name):
raise ExecutionError(
f"plugin code for `{loaded.display_name}` does not match "
f"{VALID_CODE.pattern}"
)

return Plugins(
checkers=Checkers(
tree=tree,
Expand Down
60 changes: 60 additions & 0 deletions tests/unit/plugins/finder_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,37 @@ def _loaded(plugin=None, obj=None, parameters=None):
return finder.LoadedPlugin(plugin, obj, parameters)


@pytest.mark.parametrize(
"s",
(
"E",
"E1",
"E123",
"ABC",
"ABC1",
"ABC123",
),
)
def test_valid_plugin_prefixes(s):
assert finder.VALID_CODE.match(s)


@pytest.mark.parametrize(
"s",
(
"",
"A1234",
"ABCD",
"abc",
"a-b",
"☃",
"A𝟗",
),
)
def test_invalid_plugin_prefixes(s):
assert finder.VALID_CODE.match(s) is None


def test_loaded_plugin_entry_name_vs_display_name():
loaded = _loaded(_plugin(package="package-name", ep=_ep(name="Q")))
assert loaded.entry_name == "Q"
Expand Down Expand Up @@ -761,6 +792,35 @@ def test_classify_plugins_enable_a_disabled_plugin():
)


def test_classify_plugins_does_not_error_on_reporter_prefix():
# these are ok, don't check their name
plugin = _plugin(ep=_ep(name="report-er", group="flake8.report"))
loaded = _loaded(plugin=plugin)

opts = finder.PluginOptions.blank()
classified = finder._classify_plugins([loaded], opts)

assert classified == finder.Plugins(
checkers=finder.Checkers([], [], []),
reporters={"report-er": loaded},
disabled=[],
)


def test_classify_plugins_errors_on_incorrect_checker_name():
plugin = _plugin(ep=_ep(name="INVALID", group="flake8.extension"))
loaded = _loaded(plugin=plugin, parameters={"tree": True})

with pytest.raises(ExecutionError) as excinfo:
finder._classify_plugins([loaded], finder.PluginOptions.blank())

(msg,) = excinfo.value.args
assert msg == (
"plugin code for `local[INVALID]` "
"does not match ^[A-Z]{1,3}[0-9]{0,3}$"
)


@pytest.mark.usefixtures("reset_sys")
def test_load_plugins():
plugin = _plugin(ep=_ep(value="aplugin:ExtensionTestPlugin2"))
Expand Down

0 comments on commit 7e1e8b3

Please sign in to comment.