From 269d5e0a3ea5823a5dc7eeff9902cb7062017430 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 20 Mar 2023 15:00:22 -0600 Subject: [PATCH] Added validation for project working environment names --- HISTORY.rst | 1 + docs | 2 +- platformio/project/config.py | 22 +++++++++++++++++----- platformio/project/exception.py | 7 +++++++ tests/project/test_config.py | 22 +++++++++++++++++++--- 5 files changed, 45 insertions(+), 9 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 317e9a4b..5718e304 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -20,6 +20,7 @@ PlatformIO Core 6 * Improved source file filtering functionality for the `Static Code Analysis `__ feature, making it easier to analyze only the code you need to * Added the ability to show a detailed library dependency tree only in `verbose mode `__, which can help you understand the relationship between libraries and troubleshoot issues more effectively (`issue #4517 `_) * Added the ability to run only the `device monitor `__ when using the `pio run -t monitor `__ command, saving you time and resources by skipping the build process +* Added validation for `project working environment names `__ to ensure that they only contain lowercase letters ``a-z``, numbers ``0-9``, and special characters ``_`` (underscore) and ``-`` (hyphen) * Implemented a fix for shell injection vulnerabilities when converting INO files to CPP, ensuring your code is safe and secure (`issue #4532 `_) * Restored the project generator for the `NetBeans IDE `__, providing you with more flexibility and options for your development workflow diff --git a/docs b/docs index ea46b38c..24b6ec77 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit ea46b38c806aff3f944ffba3de776cf7e1a03947 +Subproject commit 24b6ec7743d6a4553ae3c9ef6b7c991a63abdb65 diff --git a/platformio/project/config.py b/platformio/project/config.py index 43d15f3e..bf5870c9 100644 --- a/platformio/project/config.py +++ b/platformio/project/config.py @@ -39,6 +39,7 @@ CONFIG_HEADER = """ class ProjectConfigBase: + ENVNAME_RE = re.compile(r"^[a-z\d\_\-]+$", flags=re.I) INLINE_COMMENT_RE = re.compile(r"\s+;.*$") VARTPL_RE = re.compile(r"\$\{([^\.\}\()]+)\.([^\}]+)\}") @@ -388,16 +389,27 @@ class ProjectConfigBase: def validate(self, envs=None, silent=False): if not os.path.isfile(self.path): raise exception.NotPlatformIOProjectError(os.path.dirname(self.path)) + + known_envs = set(self.envs()) + # check envs - known = set(self.envs()) - if not known: + if not known_envs: raise exception.ProjectEnvsNotAvailableError() - unknown = set(list(envs or []) + self.default_envs()) - known - if unknown: - raise exception.UnknownEnvNamesError(", ".join(unknown), ", ".join(known)) + unknown_envs = set(list(envs or []) + self.default_envs()) - known_envs + if unknown_envs: + raise exception.UnknownEnvNamesError( + ", ".join(unknown_envs), ", ".join(known_envs) + ) + + # check envs names + for env in known_envs: + if not self.ENVNAME_RE.match(env): + raise exception.InvalidEnvNameError(env) + if not silent: for warning in self.warnings: click.secho("Warning! %s" % warning, fg="yellow") + return True diff --git a/platformio/project/exception.py b/platformio/project/exception.py index 8e598e03..95681bc0 100644 --- a/platformio/project/exception.py +++ b/platformio/project/exception.py @@ -43,5 +43,12 @@ class UnknownEnvNamesError(ProjectError, UserSideException): MESSAGE = "Unknown environment names '{0}'. Valid names are '{1}'" +class InvalidEnvNameError(ProjectError, UserSideException): + MESSAGE = ( + "Invalid environment name '{0}'. The name can contain " + "alphanumeric, underscore, and hyphen characters (a-z, 0-9, -, _)" + ) + + class ProjectOptionValueError(ProjectError, UserSideException): MESSAGE = "{0} for option `{1}` in section [{2}]" diff --git a/tests/project/test_config.py b/tests/project/test_config.py index 6076a7d6..f559502e 100644 --- a/tests/project/test_config.py +++ b/tests/project/test_config.py @@ -23,7 +23,11 @@ import pytest from platformio import fs from platformio.project.config import ProjectConfig -from platformio.project.exception import InvalidProjectConfError, UnknownEnvNamesError +from platformio.project.exception import ( + InvalidEnvNameError, + InvalidProjectConfError, + UnknownEnvNamesError, +) BASE_CONFIG = """ [platformio] @@ -662,9 +666,21 @@ upload_tool = two [c] upload_tool = three -[env:native] +[env:na_ti-ve13] extends = a, b, c """ ) config = ProjectConfig(str(project_conf)) - assert config.get("env:native", "upload_tool") == "three" + assert config.get("env:na_ti-ve13", "upload_tool") == "three" + + +def test_invalid_env_names(tmp_path: Path): + project_conf = tmp_path / "platformio.ini" + project_conf.write_text( + """ +[env:app:1] + """ + ) + config = ProjectConfig(str(project_conf)) + with pytest.raises(InvalidEnvNameError, match=r".*Invalid environment name 'app:1"): + config.validate()