Repository navigation
email: uncaught IndexError in the header parser on empty-input edge cases #151857
Description
The modern email header parser (email._header_value_parser, used under EmailPolicy / email.policy.default) raises a bare IndexError instead of a HeaderParseError / defect on three malformed inputs. The shared root cause is the same bug class: an empty parser token-list or string is indexed (value[0] / res[-1]) without first checking it is non-empty, so the parser escapes its own error-recovery contract.
Instance 1: MIME parameter name ending with *
import email, email.policy
email.message_from_string("Content-Type: text/plain; name*\n\n",
policy=email.policy.default)['content-type'].paramsget_parameter consumes the extended-parameter marker *, leaving value == '', then evaluates value[0], which raises IndexError. parse_mime_parameters only catches HeaderParseError, so the IndexError escapes. Also reachable via name*0* (sectioned) and a trailing x=1; name*.
Instance 2: address display name that is only a comment
email.message_from_string("To: (c):\n\n", policy=email.policy.default)['to']
email.message_from_string("Cc: (x): a@b.com;\n\n", policy=email.policy.default)['cc']DisplayName.display_name guards the empty-list case, but when the name is a single cfws token, res.pop(0) empties res and the subsequent res[-1] raises IndexError (this also propagates through the .value property). The second example is a syntactically valid RFC 5322 group whose display name is a comment.
Instance 3: empty quoted RFC 2231 extended value
email.message_from_string("Content-Type: text/plain; name*=\"'\"\n\n",
policy=email.policy.default)['content-type'].paramsThe quoted extended-value recovery in get_parameter builds an empty Value, and Value.stripped_value then does self[0]. Also reachable with name*="''", name*="us-ascii''", name*0*="'" and filename*="'".
All three are reachable from ordinary parsing of untrusted/malformed address and parameter headers under the modern policies.
Fix
Add minimal guards so each input degrades to the existing recovery path (a parse defect / empty display name), matching how the parser already treats other malformed input.
Calling the low-level get_* token parsers directly with an empty string still raises IndexError, but every caller checks for that first.
Affected versions
All three reproduce on main. The affected code (get_parameter, DisplayName.display_name and Value.stripped_value) has been present since well before 3.9.
Activity
pythongh-151857: Fix IndexError in the email header parser on empty i…
pythongh-151857: Handle an empty quoted RFC 2231 value in the email p…