From 3ca52dc55c01ca0ba3de6ee7087277ea5d44ade5 Mon Sep 17 00:00:00 2001 From: Riccardo Schirone Date: Thu, 6 Oct 2022 14:09:48 +0200 Subject: [PATCH] Raise RequirementsFileParseError when missing closing quotation shlex.split, used to split options in requirements.txt files, might raise a ValueError when the input string is not well formed. Catch the ValueError and re-raise it as a RequirementsFileParseError instead. --- news/11491.bugfix.rst | 1 + src/pip/_internal/req/req_file.py | 7 ++++++- tests/unit/test_req_file.py | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 news/11491.bugfix.rst diff --git a/news/11491.bugfix.rst b/news/11491.bugfix.rst new file mode 100644 index 000000000..a8f53927f --- /dev/null +++ b/news/11491.bugfix.rst @@ -0,0 +1 @@ +Raise RequirementsFileParseError when parsing malformed requirements options that can't be sucessfully parsed by shlex. diff --git a/src/pip/_internal/req/req_file.py b/src/pip/_internal/req/req_file.py index 06ea6f277..1f0a277e1 100644 --- a/src/pip/_internal/req/req_file.py +++ b/src/pip/_internal/req/req_file.py @@ -397,7 +397,12 @@ def get_line_parser(finder: Optional["PackageFinder"]) -> LineParser: args_str, options_str = break_args_options(line) - opts, _ = parser.parse_args(shlex.split(options_str), defaults) + try: + options = shlex.split(options_str) + except ValueError as e: + raise OptionParsingError(f"Could not split options: {options_str}") from e + + opts, _ = parser.parse_args(options, defaults) return args_str, opts diff --git a/tests/unit/test_req_file.py b/tests/unit/test_req_file.py index 6b3712b0c..76fac40ad 100644 --- a/tests/unit/test_req_file.py +++ b/tests/unit/test_req_file.py @@ -786,6 +786,20 @@ class TestParseRequirements: assert not reqs + def test_invalid_options(self, tmpdir: Path, finder: PackageFinder) -> None: + """ + Test parsing invalid options such as missing closing quotation + """ + with open(tmpdir.joinpath("req1.txt"), "w") as fp: + fp.write("--'data\n") + + with pytest.raises(RequirementsFileParseError): + list( + parse_reqfile( + tmpdir.joinpath("req1.txt"), finder=finder, session=PipSession() + ) + ) + def test_req_file_parse_comment_end_of_line_with_url( self, tmpdir: Path, finder: PackageFinder ) -> None: