Skip to content

Commit

Permalink
[Fix] Fix O(N^2) algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
vstakhov committed Dec 12, 2019
1 parent fd3caeb commit eba3b15
Showing 1 changed file with 30 additions and 13 deletions.
43 changes: 30 additions & 13 deletions src/libmime/mime_expressions.c
Expand Up @@ -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

Expand All @@ -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");
Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit eba3b15

Please sign in to comment.