X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/89b1a5980cf39a0f34186a4c91c3b316c7b2f831..d8b76fa95c55331db4f475ee34caa7e8725ec421:/src/src/match.c diff --git a/src/src/match.c b/src/src/match.c index 6a3314194..6415b993d 100644 --- a/src/src/match.c +++ b/src/src/match.c @@ -3,7 +3,7 @@ *************************************************/ /* Copyright (c) University of Cambridge 1995 - 2018 */ -/* Copyright (c) The Exim Maintainers 2020 */ +/* Copyright (c) The Exim Maintainers 2020 - 2021 */ /* See the file NOTICE for conditions of use and distribution. */ /* Functions for matching strings */ @@ -128,9 +128,9 @@ required. */ if (pattern[0] == '^') { - const pcre * re = regex_must_compile(pattern, cb->caseless, FALSE); + const pcre2_code * re = regex_must_compile(pattern, cb->caseless, FALSE); if (expand_setup < 0 - ? pcre_exec(re, NULL, CCS s, Ustrlen(s), 0, PCRE_EOPT, NULL, 0) < 0 + ? !regex_match(re, s, -1, NULL) : !regex_match_and_setup(re, s, 0, expand_setup) ) return FAIL; @@ -498,8 +498,18 @@ else } /* For an unnamed list, use the expanded version in comments */ +#define LIST_LIMIT_PR 2048 -HDEBUG(D_any) if (!ot) ot = string_sprintf("%s in \"%s\"?", name, list); +HDEBUG(D_any) if (!ot) + { + int n, m; + gstring * g = string_fmt_append(NULL, "%s in \"%n%.*s%n\"", + name, &n, LIST_LIMIT_PR, list, &m); + if (m - n >= LIST_LIMIT_PR) g = string_catn(g, US"...", 3); + g = string_catn(g, US"?", 1); + gstring_release_unused(g); + ot = string_from_gstring(g); + } /* Now scan the list and process each item in turn, until one of them matches, or we hit an error. */ @@ -705,7 +715,7 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0))) if ((bits & (-bits)) == bits) /* Only one of the two bits is set */ { HDEBUG(D_lists) debug_printf("%s %s (matched \"%s\"%s)\n", ot, - (yield == OK)? "yes" : "no", sss, cached); + yield == OK ? "yes" : "no", sss, cached); return yield; } } @@ -809,19 +819,19 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0))) sss = ss + 1; } - ss = filebuffer + Ustrlen(filebuffer); /* trailing space */ + ss = filebuffer + Ustrlen(filebuffer); /* trailing space */ while (ss > filebuffer && isspace(ss[-1])) ss--; *ss = 0; ss = filebuffer; - while (isspace(*ss)) ss++; /* leading space */ + while (isspace(*ss)) ss++; /* leading space */ - if (*ss == 0) continue; /* ignore empty */ + if (!*ss) continue; /* ignore empty */ - file_yield = yield; /* positive yield */ - sss = ss; /* for debugging */ + file_yield = yield; /* positive yield */ + sss = ss; /* for debugging */ - if (*ss == '!') /* negation */ + if (*ss == '!') /* negation */ { file_yield = (file_yield == OK)? FAIL : OK; while (isspace((*(++ss)))); @@ -833,6 +843,11 @@ while ((sss = string_nextinlist(&list, &sep, NULL, 0))) (void)fclose(f); HDEBUG(D_lists) debug_printf("%s %s (matched \"%s\" in %s)\n", ot, yield == OK ? "yes" : "no", sss, filename); + + /* The "pattern" being matched came from the file; we use a stack-local. + Copy it to allocated memory now we know it matched. */ + + if (valueptr) *valueptr = string_copy(ss); return file_yield; case DEFER: @@ -1061,7 +1076,6 @@ if (pattern[0] == '@' && pattern[1] == '@') { int watchdog = 50; uschar *list, *ss; - uschar buffer[1024]; if (sdomain == subject + 1 && *subject == '*') return FAIL; @@ -1092,7 +1106,7 @@ if (pattern[0] == '@' && pattern[1] == '@') /* Look up the local parts provided by the list; negation is permitted. If a local part has to begin with !, a regex can be used. */ - while ((ss = string_nextinlist(CUSS &list, &sep, buffer, sizeof(buffer)))) + while ((ss = string_nextinlist(CUSS &list, &sep, NULL, 0))) { int local_yield; @@ -1269,9 +1283,11 @@ compared. Therefore, Exim now forces the entire address into lower case here, provided that "caseless" is set. (It is FALSE for calls for matching rewriting patterns.) Otherwise just the domain is lower cases. A magic item "+caseful" in the list can be used to restore a caseful copy of the local part from the -original address. */ +original address. +Limit the subject address size to avoid mem-exhaustion attacks. The size chosen +is historical (we used to use big_buffer here). */ -if ((len = Ustrlen(address)) > 255) len = 255; +if ((len = Ustrlen(address)) > BIG_BUFFER_SIZE) len = BIG_BUFFER_SIZE; ab.address = string_copyn(address, len); for (uschar * p = ab.address + len - 1; p >= ab.address; p--)