From ab3817f4912751de1ca3d395ceca80dc03100929 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Wed, 13 Dec 2017 20:35:48 +0000 Subject: [PATCH] [Minor] Add some tags limit to avoid HTML parser DoS --- src/libserver/html.c | 51 +++++++++++++++++++++++++++++--------------- src/libserver/html.h | 2 ++ 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/libserver/html.c b/src/libserver/html.c index fc08baeb5..26318db43 100644 --- a/src/libserver/html.c +++ b/src/libserver/html.c @@ -28,6 +28,7 @@ static sig_atomic_t tags_sorted = 0; static sig_atomic_t entities_sorted = 0; +static const guint max_tags = 8192; /* Ignore tags if this maximum is reached */ struct html_tag_def { const gchar *name; @@ -997,8 +998,13 @@ rspamd_html_process_tag (rspamd_mempool_t *pool, struct html_content *hc, nnode); } + if (hc->total_tags > max_tags) { + hc->flags |= RSPAMD_HTML_FLAG_TOO_MANY_TAGS; + } + if (tag->id == -1) { /* Ignore unknown tags */ + hc->total_tags ++; return FALSE; } @@ -1006,25 +1012,26 @@ rspamd_html_process_tag (rspamd_mempool_t *pool, struct html_content *hc, if (!(tag->flags & CM_INLINE)) { /* Block tag */ - nnode = g_node_new (tag); - if (tag->flags & (FL_CLOSING|FL_CLOSED)) { if (!*cur_level) { msg_debug_html ("bad parent node"); - g_node_destroy (nnode); return FALSE; } - g_node_append (*cur_level, nnode); + if (hc->total_tags < max_tags) { + nnode = g_node_new (tag); + g_node_append (*cur_level, nnode); - if (!rspamd_html_check_balance (nnode, cur_level)) { - msg_debug_html ( - "mark part as unbalanced as it has not pairable closing tags"); - hc->flags |= RSPAMD_HTML_FLAG_UNBALANCED; - *balanced = FALSE; - } - else { - *balanced = TRUE; + if (!rspamd_html_check_balance (nnode, cur_level)) { + msg_debug_html ( + "mark part as unbalanced as it has not pairable closing tags"); + hc->flags |= RSPAMD_HTML_FLAG_UNBALANCED; + *balanced = FALSE; + } else { + *balanced = TRUE; + } + + hc->total_tags ++; } } else { @@ -1043,8 +1050,13 @@ rspamd_html_process_tag (rspamd_mempool_t *pool, struct html_content *hc, hc->flags |= RSPAMD_HTML_FLAG_UNBALANCED; *balanced = FALSE; tag->parent = parent->parent; - g_node_append (parent->parent, nnode); - *cur_level = nnode; + + if (hc->total_tags < max_tags) { + nnode = g_node_new (tag); + g_node_append (parent->parent, nnode); + *cur_level = nnode; + hc->total_tags ++; + } return TRUE; } @@ -1053,10 +1065,15 @@ rspamd_html_process_tag (rspamd_mempool_t *pool, struct html_content *hc, parent->content_length += tag->content_length; } - g_node_append (*cur_level, nnode); + if (hc->total_tags < max_tags) { + nnode = g_node_new (tag); + g_node_append (*cur_level, nnode); + + if ((tag->flags & FL_CLOSED) == 0) { + *cur_level = nnode; + } - if ((tag->flags & FL_CLOSED) == 0) { - *cur_level = nnode; + hc->total_tags ++; } if (tag->flags & (CM_HEAD|CM_UNKNOWN|FL_IGNORE)) { diff --git a/src/libserver/html.h b/src/libserver/html.h index 5216ad767..84d5e2bc2 100644 --- a/src/libserver/html.h +++ b/src/libserver/html.h @@ -17,6 +17,7 @@ #define RSPAMD_HTML_FLAG_UNBALANCED (1 << 3) #define RSPAMD_HTML_FLAG_UNKNOWN_ELEMENTS (1 << 4) #define RSPAMD_HTML_FLAG_DUPLICATE_ELEMENTS (1 << 5) +#define RSPAMD_HTML_FLAG_TOO_MANY_TAGS (1 << 6) /* * Image flags @@ -107,6 +108,7 @@ struct rspamd_task; struct html_content { GNode *html_tags; gint flags; + guint total_tags; struct html_color bgcolor; guchar *tags_seen; GPtrArray *images; -- 2.39.5