]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] message: make newline metadata budget task-global, fix flag collision
authorVsevolod Stakhov <vsevolod@rspamd.com>
Thu, 23 Jul 2026 10:10:56 +0000 (11:10 +0100)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Thu, 23 Jul 2026 10:10:56 +0000 (11:10 +0100)
src/libmime/message.c
src/libmime/message.h

index 7722ffc22fc2b3c8814f489830834e60d7c11a2e..9589096fa806d4cb4ec979b4ee7d89ef34dfb7f9 100644 (file)
@@ -231,17 +231,26 @@ rspamd_mime_part_detect_language(struct rspamd_task *task,
        }
 }
 
-/* Bound per-part newline metadata; the text itself is still normalized fully */
-static const unsigned int max_part_newlines = 100000;
+/* Bound newline metadata for the whole message; the text itself is still normalized fully */
+static const unsigned int max_message_newlines = 100000;
 
 static inline void
-rspamd_text_part_maybe_add_newline(struct rspamd_mime_text_part *part)
+rspamd_text_part_maybe_add_newline(struct rspamd_task *task,
+                                                                  struct rspamd_mime_text_part *part)
 {
-       if (G_LIKELY(part->newlines->len < max_part_newlines)) {
+       if (G_LIKELY(MESSAGE_FIELD(task, ntext_newlines) < max_message_newlines)) {
                g_ptr_array_add(part->newlines,
                                                (((gpointer) (goffset) (part->utf_stripped_content->len))));
+               MESSAGE_FIELD(task, ntext_newlines) += 1;
        }
        else {
+               if (!MESSAGE_FIELD(task, text_newlines_limit_reached)) {
+                       msg_warn_task("too many newlines in message; only %ud newline "
+                                                 "positions are recorded across all text parts",
+                                                 max_message_newlines);
+                       MESSAGE_FIELD(task, text_newlines_limit_reached) = TRUE;
+               }
+
                part->flags |= RSPAMD_MIME_TEXT_PART_FLAG_NEWLINES_TRUNCATED;
        }
 }
@@ -325,7 +334,7 @@ rspamd_strip_newlines_parse(struct rspamd_task *task,
                                        g_byte_array_append(part->utf_stripped_content,
                                                                                (const uint8_t *) " ", 1);
                                        crlf_added = TRUE;
-                                       rspamd_text_part_maybe_add_newline(part);
+                                       rspamd_text_part_maybe_add_newline(task, part);
                                }
 
                                part->nlines++;
@@ -358,7 +367,7 @@ rspamd_strip_newlines_parse(struct rspamd_task *task,
                                if (IS_TEXT_PART_HTML(part) || !url_open_bracket) {
                                        g_byte_array_append(part->utf_stripped_content,
                                                                                (const uint8_t *) " ", 1);
-                                       rspamd_text_part_maybe_add_newline(part);
+                                       rspamd_text_part_maybe_add_newline(task, part);
                                        crlf_added = TRUE;
                                }
                                else {
@@ -375,7 +384,7 @@ rspamd_strip_newlines_parse(struct rspamd_task *task,
                                                crlf_added = TRUE;
                                        }
 
-                                       rspamd_text_part_maybe_add_newline(part);
+                                       rspamd_text_part_maybe_add_newline(task, part);
                                }
 
                                c = p + 1;
@@ -388,7 +397,7 @@ rspamd_strip_newlines_parse(struct rspamd_task *task,
                                        g_byte_array_append(part->utf_stripped_content,
                                                                                (const uint8_t *) " ", 1);
                                        crlf_added = TRUE;
-                                       rspamd_text_part_maybe_add_newline(part);
+                                       rspamd_text_part_maybe_add_newline(task, part);
                                }
 
                                part->nlines++;
@@ -441,7 +450,7 @@ rspamd_strip_newlines_parse(struct rspamd_task *task,
                                part->nlines++;
 
                                if (!crlf_added) {
-                                       rspamd_text_part_maybe_add_newline(part);
+                                       rspamd_text_part_maybe_add_newline(task, part);
                                }
 
                                /* Skip initial spaces */
@@ -508,7 +517,7 @@ rspamd_strip_newlines_parse(struct rspamd_task *task,
                        if (!crlf_added) {
                                g_byte_array_append(part->utf_stripped_content,
                                                                        (const uint8_t *) " ", 1);
-                               rspamd_text_part_maybe_add_newline(part);
+                               rspamd_text_part_maybe_add_newline(task, part);
                        }
 
                        part->nlines++;
@@ -546,12 +555,6 @@ rspamd_normalize_text_part(struct rspamd_task *task,
 
                rspamd_strip_newlines_parse(task, p, end, part);
 
-               if (part->flags & RSPAMD_MIME_TEXT_PART_FLAG_NEWLINES_TRUNCATED) {
-                       msg_warn_task("too many newlines in text part; only %ud newline "
-                                                 "positions are recorded",
-                                                 max_part_newlines);
-               }
-
                for (i = 0; i < part->newlines->len; i++) {
                        ex = rspamd_mempool_alloc(task->task_pool, sizeof(*ex));
                        off = (goffset) g_ptr_array_index(part->newlines, i);
index 34cf99c97d0c3f89a64f3494d502a59c95851d9f..dff270f96942cbc9d8a0d81a204b373f46c593fb 100644 (file)
@@ -121,8 +121,8 @@ struct rspamd_mime_part {
 #define RSPAMD_MIME_TEXT_PART_FLAG_HTML (1 << 2)
 #define RSPAMD_MIME_TEXT_PART_FLAG_8BIT_RAW (1 << 3)
 #define RSPAMD_MIME_TEXT_PART_FLAG_8BIT_ENCODED (1 << 4)
-#define RSPAMD_MIME_TEXT_PART_FLAG_NEWLINES_TRUNCATED (1 << 5)
 #define RSPAMD_MIME_TEXT_PART_ATTACHMENT (1 << 5)
+#define RSPAMD_MIME_TEXT_PART_FLAG_NEWLINES_TRUNCATED (1 << 6)
 
 #define IS_TEXT_PART_EMPTY(part) ((part)->flags & RSPAMD_MIME_TEXT_PART_FLAG_EMPTY)
 #define IS_TEXT_PART_UTF(part) ((part)->flags & RSPAMD_MIME_TEXT_PART_FLAG_UTF)