]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-134152: Fix UnboundLocalError in email._header_value_parser _get_ptext_to_endchars...
authorR. David Murray <rdmurray@bitdance.com>
Sun, 25 May 2025 22:09:32 +0000 (18:09 -0400)
committerGitHub <noreply@github.com>
Sun, 25 May 2025 22:09:32 +0000 (18:09 -0400)
Fix an UnboundLocalError that can occur when parsing certain delimited constructs in headers (domain literals, quoted strings, comments). After the fix the _get_ptext_to_endchars returns an empty string if there is no content after the opening delimiter. The calling code is responsible for handling the lack of the trailing delimiter, which it already does; this edge case was the header ending immediately after the opening delimiter.

Lib/email/_header_value_parser.py
Lib/test/test_email/test__header_value_parser.py
Misc/NEWS.d/next/Library/2025-05-19-10-32-11.gh-issue-134152.INJC2j.rst [new file with mode: 0644]

index 9a51b9437333db8addbe03195afcb86d18068d80..f11fa83d45ed2d39d6631380879ff0664c5b7037 100644 (file)
@@ -1020,6 +1020,8 @@ def _get_ptext_to_endchars(value, endchars):
     a flag that is True iff there were any quoted printables decoded.
 
     """
+    if not value:
+        return '', '', False
     fragment, *remainder = _wsp_splitter(value, 1)
     vchars = []
     escape = False
index ac12c3b2306f7d7bcc93569af1d976e8ce4506f0..fd4ac2c404ce473f5ce0dbd201e271825423d1c8 100644 (file)
@@ -463,6 +463,19 @@ class TestParser(TestParserMixin, TestEmailBase):
                                 [errors.NonPrintableDefect], ')')
         self.assertEqual(ptext.defects[0].non_printables[0], '\x00')
 
+    def test_get_qp_ctext_close_paren_only(self):
+        self._test_get_x(parser.get_qp_ctext,
+                        ')', '', ' ', [], ')')
+
+    def test_get_qp_ctext_open_paren_only(self):
+        self._test_get_x(parser.get_qp_ctext,
+                        '(', '', ' ', [], '(')
+
+    def test_get_qp_ctext_no_end_char(self):
+        self._test_get_x(parser.get_qp_ctext,
+                        '', '', ' ', [], '')
+
+
     # get_qcontent
 
     def test_get_qcontent_only(self):
@@ -503,6 +516,14 @@ class TestParser(TestParserMixin, TestEmailBase):
                                 [errors.NonPrintableDefect], '"')
         self.assertEqual(ptext.defects[0].non_printables[0], '\x00')
 
+    def test_get_qcontent_empty(self):
+        self._test_get_x(parser.get_qcontent,
+                         '"', '', '', [], '"')
+
+    def test_get_qcontent_no_end_char(self):
+        self._test_get_x(parser.get_qcontent,
+                         '', '', '', [], '')
+
     # get_atext
 
     def test_get_atext_only(self):
@@ -1283,6 +1304,18 @@ class TestParser(TestParserMixin, TestEmailBase):
         self._test_get_x(parser.get_dtext,
                         'foo[bar', 'foo', 'foo', [], '[bar')
 
+    def test_get_dtext_open_bracket_only(self):
+        self._test_get_x(parser.get_dtext,
+                        '[', '', '', [], '[')
+
+    def test_get_dtext_close_bracket_only(self):
+        self._test_get_x(parser.get_dtext,
+                        ']', '', '', [], ']')
+
+    def test_get_dtext_empty(self):
+        self._test_get_x(parser.get_dtext,
+                        '', '', '', [], '')
+
     # get_domain_literal
 
     def test_get_domain_literal_only(self):
diff --git a/Misc/NEWS.d/next/Library/2025-05-19-10-32-11.gh-issue-134152.INJC2j.rst b/Misc/NEWS.d/next/Library/2025-05-19-10-32-11.gh-issue-134152.INJC2j.rst
new file mode 100644 (file)
index 0000000..6da3d41
--- /dev/null
@@ -0,0 +1,2 @@
+Fixed :exc:`UnboundLocalError` that could occur during :mod:`email` header
+parsing if an expected trailing delimiter is missing in some contexts.