X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/19849de0dd5a6cf2ec8344a8adef9a433d7e7cf1..ef2e5890df09193717f9d345ffaaa406e2d8aae7:/src/src/filter.c diff --git a/src/src/filter.c b/src/src/filter.c index 402ad6ae5..c5ef678b6 100644 --- a/src/src/filter.c +++ b/src/src/filter.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. */ @@ -51,7 +51,7 @@ typedef struct condition_block { /* Miscellaneous other declarations */ static uschar **error_pointer; -static uschar *log_filename; +static const uschar *log_filename; static int filter_options; static int line_number; static int expect_endif; @@ -1425,10 +1425,7 @@ static BOOL test_condition(condition_block *c, BOOL toplevel) { BOOL yield = FALSE; -const pcre *re; uschar *exp[2], *p, *pp; -const uschar *regcomp_error = NULL; -int regcomp_error_offset; int val[2]; int i; @@ -1588,26 +1585,34 @@ switch (c->type) case cond_matches: case cond_MATCHES: - if ((filter_test != FTEST_NONE && debug_selector != 0) || - (debug_selector & D_filter) != 0) { - debug_printf_indent("Match expanded arguments:\n"); - debug_printf_indent(" Subject = %s\n", exp[0]); - debug_printf_indent(" Pattern = %s\n", exp[1]); - } + const pcre2_code *re; + int err; + PCRE2_SIZE offset; - if (!(re = pcre_compile(CS exp[1], - PCRE_COPT | ((c->type == cond_matches)? PCRE_CASELESS : 0), - CCSS ®comp_error, ®comp_error_offset, NULL))) - { - *error_pointer = string_sprintf("error while compiling " - "regular expression \"%s\": %s at offset %d", - exp[1], regcomp_error, regcomp_error_offset); - return FALSE; - } + if ((filter_test != FTEST_NONE && debug_selector != 0) || + (debug_selector & D_filter) != 0) + { + debug_printf_indent("Match expanded arguments:\n"); + debug_printf_indent(" Subject = %s\n", exp[0]); + debug_printf_indent(" Pattern = %s\n", exp[1]); + } - yield = regex_match_and_setup(re, exp[0], PCRE_EOPT, -1); - break; + if (!(re = pcre2_compile((PCRE2_SPTR)exp[1], PCRE2_ZERO_TERMINATED, + PCRE_COPT | (c->type == cond_matches ? PCRE2_CASELESS : 0), + &err, &offset, pcre_cmp_ctx))) + { + uschar errbuf[128]; + pcre2_get_error_message(err, errbuf, sizeof(errbuf)); + *error_pointer = string_sprintf("error while compiling " + "regular expression \"%s\": %s at offset %ld", + exp[1], errbuf, (long)offset); + return FALSE; + } + + yield = regex_match_and_setup(re, exp[0], PCRE_EOPT, -1); + break; + } /* For above and below, convert the strings to numbers */ @@ -1668,7 +1673,7 @@ Returns: FF_DELIVERED success, a significant action was taken static int interpret_commands(filter_cmd *commands, address_item **generated) { -uschar *s; +const uschar *s; int mode; address_item *addr; BOOL condition_value; @@ -1677,7 +1682,7 @@ while (commands) { int ff_ret; uschar *fmsg, *ff_name; - uschar *expargs[MAILARGS_STRING_COUNT]; + const uschar *expargs[MAILARGS_STRING_COUNT]; int i, n[2]; @@ -1709,7 +1714,7 @@ while (commands) case add_command: for (i = 0; i < 2; i++) { - uschar *ss = expargs[i]; + const uschar *ss = expargs[i]; uschar *end; if (i == 1 && (*ss++ != 'n' || ss[1] != 0)) @@ -1806,9 +1811,8 @@ while (commands) af_ignore_error flag if necessary, and the errors address, which can be set in a system filter and to the local address in user filters. */ - addr = deliver_make_addr(expargs[0], TRUE); /* TRUE => copy s */ - addr->prop.errors_address = (s == NULL)? - s : string_copy(s); /* Default is NULL */ + addr = deliver_make_addr(US expargs[0], TRUE); /* TRUE => copy s, so deconst ok */ + addr->prop.errors_address = !s ? NULL : string_copy(s); /* Default is NULL */ if (commands->noerror) addr->prop.ignore_error = TRUE; addr->next = *generated; *generated = addr; @@ -1848,7 +1852,7 @@ while (commands) af_pfr and af_file flags, the af_ignore_error flag if necessary, and the mode value. */ - addr = deliver_make_addr(s, TRUE); /* TRUE => copy s */ + addr = deliver_make_addr(US s, TRUE); /* TRUE => copy s, so deconst ok */ setflag(addr, af_pfr); setflag(addr, af_file); if (commands->noerror) addr->prop.ignore_error = TRUE; @@ -1878,7 +1882,7 @@ while (commands) each command argument is expanded in the transport after the command has been split up into separate arguments. */ - addr = deliver_make_addr(s, TRUE); /* TRUE => copy s */ + addr = deliver_make_addr(US s, TRUE); /* TRUE => copy s, so deconst ok */ setflag(addr, af_pfr); setflag(addr, af_expand_pipe); if (commands->noerror) addr->prop.ignore_error = TRUE; @@ -1952,7 +1956,7 @@ while (commands) (long int)geteuid()); if (log_fd < 0) { - if (log_filename == NULL) + if (!log_filename) { *error_pointer = US"attempt to obey \"logwrite\" command " "without a previous \"logfile\""; @@ -1961,7 +1965,7 @@ while (commands) log_fd = Uopen(log_filename, O_CREAT|O_APPEND|O_WRONLY, log_mode); if (log_fd < 0) { - *error_pointer = string_open_failed(errno, "filter log file \"%s\"", + *error_pointer = string_open_failed("filter log file \"%s\"", log_filename); return FF_ERROR; } @@ -1975,9 +1979,8 @@ while (commands) } } else - { - DEBUG(D_filter) debug_printf_indent("skipping logwrite (verifying or testing)\n"); - } + DEBUG(D_filter) + debug_printf_indent("skipping logwrite (verifying or testing)\n"); break; /* Header addition and removal is available only in the system filter. The @@ -1990,16 +1993,19 @@ while (commands) s = expargs[0]; if (filter_test != FTEST_NONE) - printf("Headers %s \"%s\"\n", (subtype == TRUE)? "add" : - (subtype == FALSE)? "remove" : "charset", string_printing(s)); + printf("Headers %s \"%s\"\n", + subtype == TRUE ? "add" + : subtype == FALSE ? "remove" + : "charset", + string_printing(s)); if (subtype == TRUE) { while (isspace(*s)) s++; - if (s[0] != 0) + if (*s) { - header_add(htype_other, "%s%s", s, (s[Ustrlen(s)-1] == '\n')? - "" : "\n"); + header_add(htype_other, "%s%s", s, + s[Ustrlen(s)-1] == '\n' ? "" : "\n"); header_last->type = header_checkname(header_last, FALSE); if (header_last->type >= 'a') header_last->type = htype_other; } @@ -2008,11 +2014,9 @@ while (commands) else if (subtype == FALSE) { int sep = 0; - uschar *ss; - const uschar *list = s; - uschar buffer[128]; - while ((ss = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) - != NULL) + const uschar * list = s; + + for (uschar * ss; ss = string_nextinlist(&list, &sep, NULL, 0); ) header_remove(0, ss); } @@ -2042,18 +2046,18 @@ while (commands) ff_name = US"freeze"; ff_ret = FF_FREEZE; - DEFERFREEZEFAIL: - fmsg = expargs[0]; - if (Ustrlen(fmsg) > 1024) Ustrcpy(fmsg + 1000, US" ... (truncated)"); - fmsg = US string_printing(fmsg); - *error_pointer = fmsg; + DEFERFREEZEFAIL: + *error_pointer = fmsg = US string_printing(Ustrlen(expargs[0]) > 1024 + ? string_sprintf("%.1000s ... (truncated)", expargs[0]) + : string_copy(expargs[0])); if (filter_test != FTEST_NONE) { indent(); printf("%c%s text \"%s\"\n", toupper(ff_name[0]), ff_name+1, fmsg); } - else DEBUG(D_filter) debug_printf_indent("Filter: %s \"%s\"\n", ff_name, fmsg); + else + DEBUG(D_filter) debug_printf_indent("Filter: %s \"%s\"\n", ff_name, fmsg); return ff_ret; case finish_command: @@ -2063,19 +2067,19 @@ while (commands) printf("%sinish\n", (commands->seen)? "Seen f" : "F"); } else - { DEBUG(D_filter) debug_printf_indent("Filter: %sfinish\n", - (commands->seen)? " Seen " : ""); - } + commands->seen ? " Seen " : ""); finish_obeyed = TRUE; - return filter_delivered? FF_DELIVERED : FF_NOTDELIVERED; + return filter_delivered ? FF_DELIVERED : FF_NOTDELIVERED; case if_command: { uschar *save_address = filter_thisaddress; int ok = FF_DELIVERED; condition_value = test_condition(commands->args[0].c, TRUE); - if (*error_pointer != NULL) ok = FF_ERROR; else + if (*error_pointer) + ok = FF_ERROR; + else { output_indent += 2; ok = interpret_commands(commands->args[condition_value? 1:2].f, @@ -2083,7 +2087,7 @@ while (commands) output_indent -= 2; } filter_thisaddress = save_address; - if (finish_obeyed || (ok != FF_DELIVERED && ok != FF_NOTDELIVERED)) + if (finish_obeyed || ok != FF_DELIVERED && ok != FF_NOTDELIVERED) return ok; } break; @@ -2095,7 +2099,7 @@ while (commands) case mail_command: case vacation_command: - if (return_path == NULL || return_path[0] == 0) + if (!return_path || !*return_path) { if (filter_test != FTEST_NONE) printf("%s command ignored because return_path is empty\n", @@ -2125,10 +2129,10 @@ while (commands) for (i = 0; i < MAILARGS_STRING_COUNT; i++) { - uschar *p; - uschar *s = expargs[i]; + const uschar *p; + const uschar *s = expargs[i]; - if (s == NULL) continue; + if (!s) continue; if (i != mailarg_index_text) for (p = s; *p != 0; p++) { @@ -2160,12 +2164,12 @@ while (commands) else { - uschar *pp; + const uschar *pp; for (pp = p + 1;; pp++) { c = *pp; if (c == ':' && pp != p + 1) break; - if (c == 0 || c == ':' || isspace(*pp)) + if (!c || c == ':' || isspace(c)) { *error_pointer = string_sprintf("\\n not followed by space or " "valid header name in \"%.1024s\" in %s command", @@ -2180,7 +2184,7 @@ while (commands) /* The string is OK */ - commands->args[i].u = s; + commands->args[i].u = s; /*XXX loses track of const */ } /* Proceed with mail or vacation command */ @@ -2195,7 +2199,7 @@ while (commands) commands->noerror ? " (noerror)" : ""); for (i = 1; i < MAILARGS_STRING_COUNT; i++) { - uschar *arg = commands->args[i].u; + const uschar *arg = commands->args[i].u; if (arg) { int len = Ustrlen(mailargs[i]); @@ -2368,8 +2372,9 @@ Returns: TRUE if the message is deemed to be personal BOOL filter_personal(string_item *aliases, BOOL scan_cc) { -uschar *self, *self_from, *self_to; -uschar *psself = NULL, *psself_from = NULL, *psself_to = NULL; +const uschar *self, *self_from, *self_to; +uschar *psself = NULL; +const uschar *psself_from = NULL, *psself_to = NULL; rmark reset_point = store_mark(); BOOL yield; header_line *h; @@ -2503,7 +2508,7 @@ filter_interpret(uschar *filter, int options, address_item **generated, int i; int yield = FF_ERROR; uschar *ptr = filter; -uschar *save_headers_charset = headers_charset; +const uschar *save_headers_charset = headers_charset; filter_cmd *commands = NULL; filter_cmd **lastcmdptr = &commands;