gh-143921: Narrow the control character check in imaplib commands (GH-153067)

Only NUL, CR and LF are rejected now.  Other control characters are
valid in quoted strings and can occur in mailbox names returned by
the server, so they are now accepted and sent quoted.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Serhiy Storchaka
2026-07-05 18:25:36 +03:00
committed by GitHub
parent 74a2438bf7
commit d0921efb66
3 changed files with 21 additions and 5 deletions
+4 -2
View File
@@ -129,7 +129,9 @@ Untagged_status = re.compile(
# We compile these in _mode_xxx.
_Literal = br'.*{(?P<size>\d+)}$'
_Untagged_status = br'\* (?P<data>\d+) (?P<type>[A-Z-]+)( (?P<data2>.*))?'
_control_chars = re.compile(b'[\x00-\x1F\x7F]')
# Only NUL, CR and LF are unsafe (they cannot be represented even in
# a quoted string); other control characters are sent quoted.
_control_chars = re.compile(b'[\x00\r\n]')
_non_astring_char = re.compile(br'[(){ \x00-\x1f\x7f-\xff%*\\"]')
_non_list_char = re.compile(br'[(){ \x00-\x1f\x7f-\xff\\"]')
_quoted = re.compile(br'"(?:[^"\\]|\\.)*+"')
@@ -1170,7 +1172,7 @@ class IMAP4:
if isinstance(arg, str):
arg = bytes(arg, self._encoding)
if _control_chars.search(arg):
raise ValueError("Control characters not allowed in commands")
raise ValueError("NUL, CR and LF not allowed in commands")
data = data + b' ' + arg
literal = self.literal
+13 -3
View File
@@ -1751,10 +1751,20 @@ class NewIMAPTestsMixin:
client.NONEXISTENT
def test_control_characters(self):
client, _ = self._setup(SimpleIMAPHandler)
for c0 in support.control_characters_c0():
client, server = self._setup(SimpleIMAPHandler)
client.login('user', 'pass')
for c in '\0\r\n':
with self.assertRaises(ValueError):
client.login(f'user{c0}', 'pass')
client.select(f'a{c}b')
# Other control characters are valid in a quoted string and can
# occur in mailbox names returned by the server, so the client
# must be able to send them back.
for c in support.control_characters_c0():
if c in '\0\r\n':
continue
typ, _ = client.select(f'a{c}b')
self.assertEqual(typ, 'OK')
self.assertEqual(server.is_selected, [f'"a{c}b"'])
# property tests
@@ -0,0 +1,4 @@
Narrow the control character check in :mod:`imaplib` commands: only NUL, CR
and LF are now rejected. Other control characters are valid in quoted
strings and can occur in mailbox names returned by the server, so they are
now accepted and sent quoted.