From 85e03244290d3fc3f98d1a5bd6b963bb21025883 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Wed, 14 Feb 2018 14:08:08 +0000 Subject: [PATCH] Macros: speedup expansion processing --- doc/doc-txt/ChangeLog | 4 ++++ src/src/exim.c | 8 ++++---- src/src/globals.c | 1 + src/src/globals.h | 1 + src/src/readconf.c | 26 ++++++++++++++++---------- 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog index 6dd768c8a..370e1b7e7 100644 --- a/doc/doc-txt/ChangeLog +++ b/doc/doc-txt/ChangeLog @@ -99,6 +99,10 @@ JH/17 Bug 2113: Fix conversation closedown with the Avast malware scanner. JH/18 Bug 2239: Enforce non-usability of control=utf8_downconvert in the mail ACL. Previously, a crash would result. +JH/19 Speed up macro lookups during configuration file read, by skipping non- + macro text after a replacement (previously it was only once per line) and + by skipping builtin macros when searching for an uppercase lead character. + Exim version 4.90 ----------------- diff --git a/src/src/exim.c b/src/src/exim.c index 327a8ecfe..fe1b1c19d 100644 --- a/src/src/exim.c +++ b/src/src/exim.c @@ -1372,7 +1372,7 @@ whites[i] = NULL; /* The list of commandline macros should be very short. Accept the N*M complexity. */ -for (m = macros; m; m = m->next) if (m->command_line) +for (m = macros_user; m; m = m->next) if (m->command_line) { found = FALSE; for (w = whites; *w; ++w) @@ -2422,14 +2422,14 @@ for (i = 1; i < argc; i++) while (isspace(*s)) s++; } - for (m = macros; m; m = m->next) + for (m = macros_user; m; m = m->next) if (Ustrcmp(m->name, name) == 0) { fprintf(stderr, "exim: duplicated -D in command line\n"); exit(EXIT_FAILURE); } - m = macro_create(string_copy(name), string_copy(s), TRUE); + m = macro_create(name, s, TRUE); if (clmacro_count >= MAX_CLMACROS) { @@ -4988,7 +4988,7 @@ if (expansion_test) /* Only admin users may see config-file macros this way */ - if (!admin_user) macros = mlast = NULL; + if (!admin_user) macros_user = macros = mlast = NULL; /* Allow $recipients for this testing */ diff --git a/src/src/globals.c b/src/src/globals.c index 762e889d1..bcc2a7a32 100644 --- a/src/src/globals.c +++ b/src/src/globals.c @@ -953,6 +953,7 @@ uschar *lookup_dnssec_authenticated = NULL; int lookup_open_max = 25; uschar *lookup_value = NULL; +macro_item *macros_user = NULL; uschar *mailstore_basename = NULL; #ifdef WITH_CONTENT_SCAN uschar *malware_name = NULL; /* Virus Name */ diff --git a/src/src/globals.h b/src/src/globals.h index 766b8a42f..d6bc96a83 100644 --- a/src/src/globals.h +++ b/src/src/globals.h @@ -566,6 +566,7 @@ extern int lookup_open_max; /* Max lookup files to cache */ extern uschar *lookup_value; /* Value looked up from file */ extern macro_item *macros; /* Configuration macros */ +extern macro_item *macros_user; /* Non-builtin configuration macros */ extern macro_item *mlast; /* Last item in macro list */ extern uschar *mailstore_basename; /* For mailstore deliveries */ #ifdef WITH_CONTENT_SCAN diff --git a/src/src/readconf.c b/src/src/readconf.c index 5d519e996..cbbef6efd 100644 --- a/src/src/readconf.c +++ b/src/src/readconf.c @@ -599,8 +599,8 @@ return US""; /* We have a new definition; append to the list. Args: - name Name of the macro. Must be in storage persistent past the call - val Expansion result for the macro. Ditto persistence. + name Name of the macro; will be copied + val Expansion result for the macro; will be copied */ macro_item * @@ -613,13 +613,15 @@ m->next = NULL; m->command_line = command_line; m->namelen = Ustrlen(name); m->replen = Ustrlen(val); -m->name = name; -m->replacement = val; +m->name = string_copy(name); +m->replacement = string_copy(val); if (mlast) mlast->next = m; else macros = m; mlast = m; +if (!macros_user) + macros_user = m; return m; } @@ -731,7 +733,7 @@ if (redef) /* We have a new definition. */ else - (void) macro_create(string_copy(name), string_copy(s), FALSE); + (void) macro_create(name, s, FALSE); return TRUE; } @@ -741,7 +743,7 @@ return TRUE; /* Process line for macros. The line is in big_buffer starting at offset len. Expand big_buffer if needed. Handle definitions of new macros, and -imacro expansions, rewriting the line in thw buffer. +macro expansions, rewriting the line in the buffer. Arguments: len Offset in buffer of start of line @@ -780,17 +782,21 @@ if (len == 0 && isupper(*s)) /* Skip leading chars which cannot start a macro name, to avoid multiple pointless rescans in Ustrstr calls. */ -while (*s && !isupper(*s) && *s != '_') s++; +while (*s && !isupper(*s) && !(*s == '_' && isupper(s[1]))) s++; /* For each defined macro, scan the line (from after XXX= if present), replacing all occurrences of the macro. */ *macro_found = FALSE; -for (m = macros; m; m = m->next) +if (*s) for (m = *s == '_' ? macros : macros_user; m; m = m->next) { uschar * p, *pp; - uschar * t = s; + uschar * t; + + while (*s && !isupper(*s) && !(*s == '_' && isupper(s[1]))) s++; + if (!*s) break; + t = s; while ((p = Ustrstr(t, m->name)) != NULL) { int moveby; @@ -824,7 +830,7 @@ for (m = macros; m; m = m->next) } Ustrncpy(p, m->replacement, m->replen); t = p + m->replen; - while (*t && !isupper(*t) && *t != '_') t++; + while (*t && !isupper(*t) && !(*t == '_' && isupper(t[1]))) t++; *macro_found = TRUE; } } -- 2.25.1