From 1ed8108307b8a10d48aaa094cd661ecdebfa48ee Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Mon, 28 Oct 2024 18:41:57 +0000 Subject: [PATCH] tidying --- src/src/daemon.c | 38 ++--- src/src/expand.c | 26 +-- src/src/functions.h | 4 +- src/src/match.c | 401 ++++++++++++++++++++++---------------------- 4 files changed, 227 insertions(+), 242 deletions(-) diff --git a/src/src/daemon.c b/src/src/daemon.c index 20e6bc05d..4272dae7a 100644 --- a/src/src/daemon.c +++ b/src/src/daemon.c @@ -1875,14 +1875,12 @@ write to stderr. */ if (f.daemon_listen && !f.inetd_wait_mode) { - int *default_smtp_port; - int sep; + int * default_smtp_port; int pct = 0; - uschar *s; + uschar * s; const uschar * list; - uschar *local_iface_source = US"local_interfaces"; - ip_address_item *ipa; - ip_address_item **pipa; + uschar * local_iface_source = US"local_interfaces"; + ip_address_item * ipa, ** pipa; /* If -oX was used, disable the writing of a pid file unless -oP was explicitly used to force it. Then scan the string given to -oX. Any items @@ -1891,23 +1889,20 @@ if (f.daemon_listen && !f.inetd_wait_mode) if (override_local_interfaces) { - gstring * new_smtp_port = NULL; - gstring * new_local_interfaces = NULL; + gstring * new_smtp_port = NULL, * new_local_interfaces = NULL; if (!override_pid_file_path) write_pid = FALSE; list = override_local_interfaces; - sep = 0; - while ((s = string_nextinlist(&list, &sep, NULL, 0))) + for (int sep = 0; s = string_nextinlist(&list, &sep, NULL, 0); ) { uschar joinstr[4]; gstring ** gp = Ustrpbrk(s, ".:") ? &new_local_interfaces : &new_smtp_port; - if (!*gp) { joinstr[0] = sep; joinstr[1] = ' '; - *gp = string_catn(*gp, US"<", 1); + *gp = string_catn(NULL, US"<", 1); } *gp = string_catn(*gp, joinstr, 2); @@ -1935,39 +1930,34 @@ if (f.daemon_listen && !f.inetd_wait_mode) build a translated list in a vector. */ list = daemon_smtp_port; - sep = 0; - while ((s = string_nextinlist(&list, &sep, NULL, 0))) + for (int sep = 0; s = string_nextinlist(&list, &sep, NULL, 0); ) pct++; default_smtp_port = store_get((pct+1) * sizeof(int), GET_UNTAINTED); list = daemon_smtp_port; - sep = 0; - for (pct = 0; - (s = string_nextinlist(&list, &sep, NULL, 0)); - pct++) - { + pct= 0; + for (int sep = 0; s = string_nextinlist(&list, &sep, NULL, 0); pct++) if (isdigit(*s)) { - uschar *end; + uschar * end; default_smtp_port[pct] = Ustrtol(s, &end, 0); if (end != s + Ustrlen(s)) log_write(0, LOG_PANIC_DIE|LOG_CONFIG, "invalid SMTP port: %s", s); } else { - struct servent *smtp_service = getservbyname(CS s, "tcp"); + struct servent * smtp_service = getservbyname(CS s, "tcp"); if (!smtp_service) log_write(0, LOG_PANIC_DIE|LOG_CONFIG, "TCP port \"%s\" not found", s); default_smtp_port[pct] = ntohs(smtp_service->s_port); } - } default_smtp_port[pct] = 0; /* Check the list of TLS-on-connect ports and do name lookups if needed */ list = tls_in.on_connect_ports; - sep = 0; /* the list isn't expanded so cannot be tainted. If it ever is we will trap here */ - while ((s = string_nextinlist(&list, &sep, big_buffer, big_buffer_size))) + for (int sep = 0; + s = string_nextinlist(&list, &sep, big_buffer, big_buffer_size); ) if (!isdigit(*s)) { gstring * g = NULL; diff --git a/src/src/expand.c b/src/src/expand.c index ebfd4d44a..fd5884306 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -5173,8 +5173,7 @@ while (*s) restore_expand_strings(save_expand_nmax, save_expand_nstring, save_expand_nlength); - if (flags & ESI_SKIPPING) continue; - break; + if (flags & ESI_SKIPPING) continue; else break; } /* If Perl support is configured, handle calling embedded perl subroutines, @@ -5474,7 +5473,7 @@ while (*s) FILE * f; uschar * sub_arg[2]; - if ((expand_forbid & RDO_READFILE) != 0) + if (expand_forbid & RDO_READFILE) { expand_string_message = US"file insertions are not permitted"; goto EXPAND_FAILED; @@ -5627,8 +5626,7 @@ while (*s) expand_string_message = US"missing '}' closing readsocket"; goto EXPAND_FAILED_CURLY; } - if (flags & ESI_SKIPPING) continue; - break; + if (flags & ESI_SKIPPING) continue; else break; /* Come here on failure to create socket, connect socket, write to the socket, or timeout on reading. If another substring follows, expand and @@ -5798,8 +5796,7 @@ while (*s) case 2: goto EXPAND_FAILED_CURLY; /* returned value is 0 */ } - if (flags & ESI_SKIPPING) continue; - break; + if (flags & ESI_SKIPPING) continue; else break; } /* Handle character translation for "tr" */ @@ -6353,8 +6350,7 @@ while (*s) restore_expand_strings(save_expand_nmax, save_expand_nstring, save_expand_nlength); - if (flags & ESI_SKIPPING) continue; - break; + if (flags & ESI_SKIPPING) continue; else break; } /* return the Nth item from a list */ @@ -6453,8 +6449,7 @@ while (*s) restore_expand_strings(save_expand_nmax, save_expand_nstring, save_expand_nlength); - if (flags & ESI_SKIPPING) continue; - break; + if (flags & ESI_SKIPPING) continue; else break; } case EITEM_LISTQUOTE: @@ -6553,8 +6548,7 @@ while (*s) restore_expand_strings(save_expand_nmax, save_expand_nstring, save_expand_nlength); - if (flags & ESI_SKIPPING) continue; - break; + if (flags & ESI_SKIPPING) continue; else break; } #endif /*DISABLE_TLS*/ @@ -6766,8 +6760,7 @@ while (*s) /* Restore preserved $item */ iterate_item = save_iterate_item; - if (flags & ESI_SKIPPING) continue; - break; + if (flags & ESI_SKIPPING) continue; else break; } case EITEM_SORT: @@ -7068,8 +7061,7 @@ while (*s) case 1: goto EXPAND_FAILED; /* when all is well, the */ case 2: goto EXPAND_FAILED_CURLY; /* returned value is 0 */ } - if (flags & ESI_SKIPPING) continue; - break; + if (flags & ESI_SKIPPING) continue; else break; } #ifdef SUPPORT_SRS diff --git a/src/src/functions.h b/src/src/functions.h index f04fe1f1b..ace6d4018 100644 --- a/src/src/functions.h +++ b/src/src/functions.h @@ -1074,7 +1074,9 @@ g->s = s; static inline gstring * gstring_append(gstring * dest, gstring * item) { -return item ? string_catn(dest, item->s, item->ptr) : dest; +return item + ? dest ? string_catn(dest, item->s, item->ptr) : item + : dest; } diff --git a/src/src/match.c b/src/src/match.c index dc88485a4..60d9cad1f 100644 --- a/src/src/match.c +++ b/src/src/match.c @@ -489,6 +489,9 @@ else } } +/* If expansion had no effect on the list text, the list-test result can +be cached */ + if (textonly_re) switch (type) { case MCL_STRING: @@ -601,203 +604,10 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0))) else yield = OK; - /* If the item does not begin with '/', it might be a + item for a named - list. Otherwise, it is just a single list entry that has to be matched. - We recognize '+' only when supplied with a tree of named lists. */ - - if (*ss != '/') - { - if (*ss == '+' && anchorptr) - { - int bits = 0, offset = 0, shift = 0; - unsigned int * use_cache_bits = original_cache_bits; - uschar * cached = US""; - namedlist_block * nb; - tree_node * t; - - HDEBUG(D_lists) - { debug_printf_indent(" start sublist %s\n", ss+1); expand_level += 2; } - - if (!(t = tree_search(*anchorptr, ss+1))) - { - log_write(0, LOG_MAIN|LOG_PANIC, "unknown named%s list \"%s\"", - type == MCL_DOMAIN ? " domain" : - type == MCL_HOST ? " host" : - type == MCL_ADDRESS ? " address" : - type == MCL_LOCALPART ? " local part" : "", - ss); - goto DEFER_RETURN; - } - nb = t->data.ptr; - - /* If the list number is negative, it means that this list is not - cacheable because it contains expansion items. */ - - if (nb->number < 0) use_cache_bits = NULL; - - /* If we have got a cache pointer, get the bits. This is not an "else" - because the pointer may be NULL from the start if caching is not - required. */ - - if (use_cache_bits) - { - offset = (nb->number)/16; - shift = ((nb->number)%16)*2; - bits = use_cache_bits[offset] & (3 << shift); - } - - /* Not previously tested or no cache - run the full test */ - - if (bits == 0) - { - int res = match_check_list(&(nb->string), 0, anchorptr, &use_cache_bits, - func, arg, type, name, valueptr); - HDEBUG(D_lists) - { expand_level -= 2; debug_printf_indent(" end sublist %s\n", ss+1); } - - switch (res) - { - case OK: bits = 1; break; - case FAIL: bits = 3; break; - case DEFER: goto DEFER_RETURN; - } - - /* If this list was uncacheable, or a sublist turned out to be - uncacheable, the value of use_cache_bits will now be NULL, even if it - wasn't before. Ensure that this is passed up to the next level. - Otherwise, remember the result of the search in the cache. */ - - if (!use_cache_bits) - *cache_ptr = NULL; - else - { - use_cache_bits[offset] |= bits << shift; - - if (valueptr) - { - int old_pool = store_pool; - namedlist_cacheblock *p; - - /* Cached data for hosts persists over more than one message, - so we use the permanent store pool */ - - store_pool = POOL_PERM; - p = store_get(sizeof(namedlist_cacheblock), GET_UNTAINTED); - p->key = string_copy(get_check_key(arg, type)); - - - p->data = *valueptr ? string_copy(*valueptr) : NULL; - store_pool = old_pool; - - p->next = nb->cache_data; - nb->cache_data = p; - if (*valueptr) - HDEBUG(D_lists) debug_printf_indent("data from lookup saved for " - "cache for %s: key '%s' value '%s'\n", ss, p->key, *valueptr); - } - } - } - - /* Previously cached; to find a lookup value, search a chain of values - and compare keys. Typically, there is only one such, but it is possible - for different keys to have matched the same named list. */ - - else - { - HDEBUG(D_lists) - { - expand_level -= 2; - debug_printf_indent("cached %s match for %s\n", - (bits & (-bits)) == bits ? "yes" : "no", ss); - } - - cached = US" - cached"; - if (valueptr) - { - const uschar *key = get_check_key(arg, type); - - for (namedlist_cacheblock * p = nb->cache_data; p; p = p->next) - if (Ustrcmp(key, p->key) == 0) - { - *valueptr = p->data; - break; - } - HDEBUG(D_lists) debug_printf_indent("cached lookup data = %s\n", *valueptr); - } - } - - /* Result of test is indicated by value in bits. For each test, we - have 00 => untested, 01 => tested yes, 11 => tested no. */ - - if ((bits & (-bits)) == bits) /* Only one of the two bits is set */ - { - HDEBUG(D_lists) debug_printf_indent("%s %s (matched \"%s\"%s)\n", ot, - yield == OK ? "yes" : "no", sss, cached); - goto YIELD_RETURN; - } - } - - /* Run the provided function to do the individual test. */ - - else - { - uschar * error = NULL; - switch ((func)(arg, ss, valueptr, &error)) - { - case OK: - HDEBUG(D_lists) debug_printf_indent("%s %s (matched \"%s\")\n", ot, - yield == OK ? "yes" : "no", sss); - goto YIELD_RETURN; - - case DEFER: - if (!error) - error = string_sprintf("DNS lookup of \"%s\" deferred", ss); - if (ignore_defer) - { - HDEBUG(D_lists) - debug_printf_indent("%s: item ignored by +ignore_defer\n", error); - break; - } - if (include_defer) - { - log_write(0, LOG_MAIN, "%s: accepted by +include_defer", error); - return OK; - } - if (!search_error_message) search_error_message = error; - goto DEFER_RETURN; - - /* The ERROR return occurs when checking hosts, when either a forward - or reverse lookup has failed. It can also occur in a match_ip list if a - non-IP address item is encountered. The error string gives details of - which it was. */ - - case ERROR: - if (ignore_unknown) - { - HDEBUG(D_lists) debug_printf_indent( - "%s: item ignored by +ignore_unknown\n", error); - } - else - { - HDEBUG(D_lists) debug_printf_indent("%s %s (%s)\n", ot, - include_unknown? "yes":"no", error); - if (!include_unknown) - { - if (LOGGING(unknown_in_list)) - log_write(0, LOG_MAIN, "list matching forced to fail: %s", error); - return FAIL; - } - log_write(0, LOG_MAIN, "%s: accepted by +include_unknown", error); - return OK; - } - } - } - } - /* If the item is a file name, we read the file and do a match attempt on each line in the file, including possibly more negation processing. */ - else + if (*ss == '/') { int file_yield = yield; /* In case empty file */ uschar * filename = ss; @@ -915,6 +725,197 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0))) yield = file_yield; (void)fclose(f); } + + /* If the item does not begin with '/', it might be a + item for a named + list. Otherwise, it is just a single list entry that has to be matched. + We recognize '+' only when supplied with a tree of named lists. */ + + else if (*ss == '+' && anchorptr) + { + int bits = 0, offset = 0, shift = 0; + unsigned int * use_cache_bits = original_cache_bits; + uschar * cached = US""; + namedlist_block * nb; + tree_node * t; + + HDEBUG(D_lists) + { debug_printf_indent(" start sublist %s\n", ss+1); expand_level += 2; } + + if (!(t = tree_search(*anchorptr, ss+1))) + { + log_write(0, LOG_MAIN|LOG_PANIC, "unknown named%s list \"%s\"", + type == MCL_DOMAIN ? " domain" : + type == MCL_HOST ? " host" : + type == MCL_ADDRESS ? " address" : + type == MCL_LOCALPART ? " local part" : "", + ss); + goto DEFER_RETURN; + } + nb = t->data.ptr; + + /* If the list number is negative, it means that this list is not + cacheable because it contains expansion items. */ + + if (nb->number < 0) use_cache_bits = NULL; + + /* If we have got a cache pointer, get the bits. This is not an "else" + because the pointer may be NULL from the start if caching is not + required. */ + + if (use_cache_bits) + { + offset = (nb->number)/16; + shift = ((nb->number)%16)*2; + bits = use_cache_bits[offset] & (3 << shift); + } + + /* Not previously tested or no cache - run the full test */ + + if (bits == 0) + { + int res = match_check_list(&(nb->string), 0, anchorptr, &use_cache_bits, + func, arg, type, name, valueptr); + HDEBUG(D_lists) + { expand_level -= 2; debug_printf_indent(" end sublist %s\n", ss+1); } + + switch (res) + { + case OK: bits = 1; break; + case FAIL: bits = 3; break; + case DEFER: goto DEFER_RETURN; + } + + /* If this list was uncacheable, or a sublist turned out to be + uncacheable, the value of use_cache_bits will now be NULL, even if it + wasn't before. Ensure that this is passed up to the next level. + Otherwise, remember the result of the search in the cache. */ + + if (!use_cache_bits) + *cache_ptr = NULL; + else + { + use_cache_bits[offset] |= bits << shift; + + if (valueptr) + { + int old_pool = store_pool; + namedlist_cacheblock *p; + + /* Cached data for hosts persists over more than one message, + so we use the permanent store pool */ + + store_pool = POOL_PERM; + p = store_get(sizeof(namedlist_cacheblock), GET_UNTAINTED); + p->key = string_copy(get_check_key(arg, type)); + + + p->data = *valueptr ? string_copy(*valueptr) : NULL; + store_pool = old_pool; + + p->next = nb->cache_data; + nb->cache_data = p; + if (*valueptr) + HDEBUG(D_lists) debug_printf_indent("data from lookup saved for " + "cache for %s: key '%s' value '%s'\n", ss, p->key, *valueptr); + } + } + } + + /* Previously cached; to find a lookup value, search a chain of values + and compare keys. Typically, there is only one such, but it is possible + for different keys to have matched the same named list. */ + + else + { + HDEBUG(D_lists) + { + expand_level -= 2; + debug_printf_indent("cached %s match for %s\n", + (bits & (-bits)) == bits ? "yes" : "no", ss); + } + + cached = US" - cached"; + if (valueptr) + { + const uschar *key = get_check_key(arg, type); + + for (namedlist_cacheblock * p = nb->cache_data; p; p = p->next) + if (Ustrcmp(key, p->key) == 0) + { + *valueptr = p->data; + break; + } + HDEBUG(D_lists) debug_printf_indent("cached lookup data = %s\n", *valueptr); + } + } + + /* Result of test is indicated by value in bits. For each test, we + have 00 => untested, 01 => tested yes, 11 => tested no. */ + + if ((bits & (-bits)) == bits) /* Only one of the two bits is set */ + { + HDEBUG(D_lists) debug_printf_indent("%s %s (matched \"%s\"%s)\n", ot, + yield == OK ? "yes" : "no", sss, cached); + goto YIELD_RETURN; + } + } + + /* Run the provided function to do the individual test. */ + + else + { + uschar * error = NULL; + switch ((func)(arg, ss, valueptr, &error)) + { + case OK: + HDEBUG(D_lists) debug_printf_indent("%s %s (matched \"%s\")\n", ot, + yield == OK ? "yes" : "no", sss); + goto YIELD_RETURN; + + case DEFER: + if (!error) + error = string_sprintf("DNS lookup of \"%s\" deferred", ss); + if (ignore_defer) + { + HDEBUG(D_lists) + debug_printf_indent("%s: item ignored by +ignore_defer\n", error); + break; + } + if (include_defer) + { + log_write(0, LOG_MAIN, "%s: accepted by +include_defer", error); + return OK; + } + if (!search_error_message) search_error_message = error; + goto DEFER_RETURN; + + /* The ERROR return occurs when checking hosts, when either a forward + or reverse lookup has failed. It can also occur in a match_ip list if a + non-IP address item is encountered. The error string gives details of + which it was. */ + + case ERROR: + if (ignore_unknown) + { + HDEBUG(D_lists) debug_printf_indent( + "%s: item ignored by +ignore_unknown\n", error); + } + else + { + HDEBUG(D_lists) debug_printf_indent("%s %s (%s)\n", ot, + include_unknown? "yes":"no", error); + if (!include_unknown) + { + if (LOGGING(unknown_in_list)) + log_write(0, LOG_MAIN, "list matching forced to fail: %s", error); + return FAIL; + } + log_write(0, LOG_MAIN, "%s: accepted by +include_unknown", error); + return OK; + } + } + } + } /* Loop for the next item on the top-level list */ /* End of list reached: if the last item was negated yield OK, else FAIL. */ @@ -1197,12 +1198,12 @@ if ((pdomain = Ustrrchr(pattern, '@'))) automatically interpreted in match_check_string. We just need to arrange that the leading @ is included in the domain. */ - if (pdomain > pattern && pdomain[-1] == '@' && - (pdomain[1] == 0 || - Ustrcmp(pdomain+1, "[]") == 0 || - Ustrcmp(pdomain+1, "mx_any") == 0 || - Ustrcmp(pdomain+1, "mx_primary") == 0 || - Ustrcmp(pdomain+1, "mx_secondary") == 0)) + if (pdomain > pattern && pdomain[-1] == '@' + && (pdomain[1] == 0 + || Ustrcmp(pdomain+1, "[]") == 0 + || Ustrcmp(pdomain+1, "mx_any") == 0 + || Ustrcmp(pdomain+1, "mx_primary") == 0 + || Ustrcmp(pdomain+1, "mx_secondary") == 0)) pdomain--; pllen = pdomain - pattern; -- 2.30.2