aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2019-12-12 17:59:36 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2019-12-12 17:59:36 +0000
commiteba3b1535d33c93949d0d53234ffb373772de1a5 (patch)
treea45fc31d81c0056284ba3b098685cf412c5124d0 /src
parentfd3caeb72c49fbbaeac72108365eee8c7f96dad1 (diff)
downloadrspamd-eba3b1535d33c93949d0d53234ffb373772de1a5.tar.gz
rspamd-eba3b1535d33c93949d0d53234ffb373772de1a5.zip
[Fix] Fix O(N^2) algorithm
Diffstat (limited to 'src')
-rw-r--r--src/libmime/mime_expressions.c43
1 files changed, 30 insertions, 13 deletions
diff --git a/src/libmime/mime_expressions.c b/src/libmime/mime_expressions.c
index e797bb9b6..ea46233ec 100644
--- a/src/libmime/mime_expressions.c
+++ b/src/libmime/mime_expressions.c
@@ -1309,6 +1309,19 @@ struct addr_list {
guint addrlen;
};
+static gint
+addr_list_cmp_func (const void *a, const void *b)
+{
+ const struct addr_list *addra = (struct addr_list *)a,
+ *addrb = (struct addr_list *)b;
+
+ if (addra->addrlen != addrb->addrlen) {
+ return addra->addrlen - addrb->addrlen;
+ }
+
+ return memcmp (addra->addr, addrb->addr, addra->addrlen);
+}
+
#define COMPARE_RCPT_LEN 3
#define MIN_RCPT_TO_COMPARE 7
@@ -1320,7 +1333,7 @@ rspamd_recipients_distance (struct rspamd_task *task, GArray * args,
struct rspamd_email_address *cur;
double threshold;
struct addr_list *ar;
- gint num, i, j, hits = 0, total = 0;
+ gint num, i, hits = 0;
if (args == NULL) {
msg_warn_task ("no parameters to function");
@@ -1356,27 +1369,31 @@ rspamd_recipients_distance (struct rspamd_task *task, GArray * args,
ar = rspamd_mempool_alloc0 (task->task_pool, num * sizeof (struct addr_list));
/* Fill array */
+ num = 0;
PTR_ARRAY_FOREACH (MESSAGE_FIELD (task, rcpt_mime), i, cur) {
- ar[i].name = cur->addr;
- ar[i].namelen = cur->addr_len;
- ar[i].addr = cur->domain;
- ar[i].addrlen = cur->domain_len;
+ if (cur->addr_len > COMPARE_RCPT_LEN) {
+ ar[num].name = cur->addr;
+ ar[num].namelen = cur->addr_len;
+ ar[num].addr = cur->domain;
+ ar[num].addrlen = cur->domain_len;
+ num ++;
+ }
}
+ qsort (ar, num, sizeof (*ar), addr_list_cmp_func);
+
/* Cycle all elements in array */
for (i = 0; i < num; i++) {
- for (j = i + 1; j < num; j++) {
- if (ar[i].namelen >= COMPARE_RCPT_LEN && ar[j].namelen >= COMPARE_RCPT_LEN &&
- rspamd_lc_cmp (ar[i].name, ar[j].name, COMPARE_RCPT_LEN) == 0) {
- /* Common name part */
- hits++;
+ if (i < num - 1) {
+ if (ar[i].namelen == ar[i + 1].namelen) {
+ if (rspamd_lc_cmp (ar[i].name, ar[i + 1].name, COMPARE_RCPT_LEN) == 0) {
+ hits++;
+ }
}
-
- total++;
}
}
- if ((hits * num / 2.) / (double)total >= threshold) {
+ if ((hits * num / 2.) / (double)num >= threshold) {
return TRUE;
}