]> dgit.raspbian.org Git - dovecot.git/commitdiff
[PATCH 12/14] lib-mail: Limit total address count per message to 100 000
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Fri, 17 Apr 2026 13:55:48 +0000 (15:55 +0200)
committerNoah Meyerhans <noahm@debian.org>
Wed, 16 Sep 2026 19:06:35 +0000 (15:06 -0400)
A message with millions of addresses across all its envelope headers can
exhaust memory when parsed (each struct message_address is ~100 bytes
regardless of whether the raw address is only a few bytes long).

Add remaining_addresses to struct message_part_data_limits, initialised to
MESSAGE_PART_DATA_MAX_TOTAL_ADDRESSES (100 000).  Pass the remaining budget
as max_addresses to message_address_parse_full() so parsing stops at the
limit, then deduct the actual count parsed from the budget.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Gbp-Pq: Name 0012-lib-mail-Limit-total-address-count-per-message-to-10.patch

src/lib-mail/message-part-data.c
src/lib-mail/message-part-data.h

index c302fe568b5241cf23dc2415ec0472e3d3c0090e..24e1a319645dc2c5af05ab6de8f606c5320417b4 100644 (file)
@@ -173,7 +173,7 @@ envelope_get_field(const char *name)
 
 void message_part_envelope_parse_from_header(pool_t pool,
        struct message_part_envelope **data,
-       struct message_part_data_limits *limits ATTR_UNUSED,
+       struct message_part_data_limits *limits,
        struct message_header_line *hdr)
 {
        struct message_part_envelope *d;
@@ -238,9 +238,12 @@ void message_part_envelope_parse_from_header(pool_t pool,
        if (addr_p != NULL) {
                message_address_parse_full(pool, hdr->full_value,
                                           hdr->full_value_len,
-                                          UINT_MAX,
+                                          limits->remaining_addresses,
                                           MESSAGE_ADDRESS_PARSE_FLAG_FILL_MISSING,
                                           &new_addr);
+               i_assert(new_addr.count <= limits->remaining_addresses);
+               limits->remaining_addresses -= new_addr.count;
+
                /* Merge multiple headers the same as if they were comma
                   separated in a single line. This is better from security
                   point of view, because attacker could intentionally write
index 1514f0daf2a0d20b5957cae3b9b9d45b7e623f6b..af09ea715e85cbe13892094d186440934610d274 100644 (file)
@@ -8,10 +8,14 @@
 
 struct message_header_line;
 
+#define MESSAGE_PART_DATA_MAX_TOTAL_ADDRESSES 100000
+
 struct message_part_data_limits {
+       unsigned int remaining_addresses;
 };
 
-#define MESSAGE_PART_DATA_LIMITS_INIT { }
+#define MESSAGE_PART_DATA_LIMITS_INIT \
+       { MESSAGE_PART_DATA_MAX_TOTAL_ADDRESSES }
 
 struct message_part_param {
        const char *name;