From: Wietse Venema Date: Sun, 22 May 2016 05:00:00 +0000 (-0500) Subject: postfix-3.2-20160522 X-Git-Tag: v3.2.0-RC1~28 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=84739fb911728282f5f5826aca4ea670da700cb1;p=thirdparty%2Fpostfix.git postfix-3.2-20160522 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index 52f161c22..4d58b31ef 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -22306,3 +22306,13 @@ Apologies for any names omitted. Portability: OpenBSD 6.0. Files: makedefs, util/sys_defs.h, dns/dns_str_resflags.c. + +20160521 + + Bugfix (introduced: Postfix beta): the never-used function + mvect_free() attempted to free memory that it has not + allocated. File: util/mvect.c. + + Cleanup: existing if/endif support for pcre and regexp + tables, in preparation for new if/endif support for cidr + tables. Files: util/dict_regexp.c, util/dict_pcre.c. diff --git a/postfix/WISHLIST b/postfix/WISHLIST index 3e97c2363..44eb73c83 100644 --- a/postfix/WISHLIST +++ b/postfix/WISHLIST @@ -6,18 +6,12 @@ Wish list: Disable -DSNAPSHOT and -DNONPROD in makedefs. - In-memory file, so that we can say pcre:{name=value, ...}, - pcre:{name=value, ...} without having to open a file. This - would not work for lmdb:, hash:, btree: etc., but it should - make texthash: equivalent to inline:. This would not be a - great example of user-friendliness, but it wouuld simplify - regression tests. + Modeline support in config files to enable/disable trailing + #comment, and to give hints about how to handle an LHS or + RHS. Maintainability: replace lengthy libmilter-API argument lists with named parameters, as with the libtls API. - - Wat's up with all the lowercase() calls in dict*c when - casefolding he search key? Fix buflen integer overflow detection in dict*sql.c. @@ -94,12 +88,9 @@ Wish list: Log command=good/bad statistics in postscreen? - Remember multiple access map BCC actions, for consistency - with header_checks. - smtpd_checks tests either must use a DNS dummy resolver (override the res_search API) or all names must be under - porcupine.org (but that does not work for address->name + test.postfix.org (but that does not work for address->name lookups, and cannot simulate some errors). Reporting the original Message-ID in a bounce message diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index a749bf2f9..c5e9d7346 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20160515" +#define MAIL_RELEASE_DATE "20160522" #define MAIL_VERSION_NUMBER "3.2" #ifdef SNAPSHOT diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index cf2fe179f..f1c5b8079 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -532,7 +532,7 @@ tests: all valid_hostname_test mac_expand_test dict_test unescape_test \ myaddrinfo_test format_tv_test ip_match_test name_mask_tests \ base32_code_test dict_thash_test surrogate_test timecmp_test \ dict_static_test dict_inline_test midna_domain_test casefold_test \ - dict_utf8_test strcasecmp_utf8_test vbuf_print_test + dict_utf8_test strcasecmp_utf8_test vbuf_print_test dict_regexp_test root_tests: @@ -605,7 +605,7 @@ dict_pcre_test: dict_open dict_pcre.in dict_pcre.map dict_pcre.ref rm -f dict_pcre.tmp dict_regexp_test: dict_open dict_regexp.in dict_regexp.map dict_regexp.ref - $(SHLIB_ENV) ./dict_open regexp:dict_regexp.map read dict_regexp.tmp + $(SHLIB_ENV) ./dict_open regexp:dict_regexp.map read &1 | sed 's/uid=[0-9][0-9][0-9]*/uid=USER/' >dict_regexp.tmp diff dict_regexp.ref dict_regexp.tmp rm -f dict_regexp.tmp @@ -1280,6 +1280,7 @@ dict_pcre.o: dict_pcre.c dict_pcre.o: dict_pcre.h dict_pcre.o: mac_parse.h dict_pcre.o: msg.h +dict_pcre.o: mvect.h dict_pcre.o: myflock.h dict_pcre.o: mymalloc.h dict_pcre.o: readlline.h @@ -1325,6 +1326,7 @@ dict_regexp.o: dict_regexp.c dict_regexp.o: dict_regexp.h dict_regexp.o: mac_parse.h dict_regexp.o: msg.h +dict_regexp.o: mvect.h dict_regexp.o: myflock.h dict_regexp.o: mymalloc.h dict_regexp.o: readlline.h @@ -1737,8 +1739,6 @@ load_file.o: vbuf.h load_file.o: vstream.h load_file.o: warn_stat.h load_lib.o: load_lib.c -load_lib.o: load_lib.h -load_lib.o: msg.h load_lib.o: sys_defs.h lowercase.o: check_arg.h lowercase.o: lowercase.c diff --git a/postfix/src/util/dict_pcre.c b/postfix/src/util/dict_pcre.c index fe388c2a2..17c500d28 100644 --- a/postfix/src/util/dict_pcre.c +++ b/postfix/src/util/dict_pcre.c @@ -60,6 +60,7 @@ #include "mac_parse.h" #include "pcre.h" #include "warn_stat.h" +#include "mvect.h" /* * Backwards compatibility. @@ -101,7 +102,6 @@ typedef struct { */ typedef struct DICT_PCRE_RULE { int op; /* DICT_PCRE_OP_MATCH/IF/ENDIF */ - int nesting; /* level of IF/ENDIF nesting */ int lineno; /* source file line number */ struct DICT_PCRE_RULE *next; /* next rule in dict */ } DICT_PCRE_RULE; @@ -120,6 +120,7 @@ typedef struct { pcre *pattern; /* compiled pattern */ pcre_extra *hints; /* hints to speed pattern execution */ int match; /* positive or negative match */ + struct DICT_PCRE_RULE *endif_rule; /* matching endif rule */ } DICT_PCRE_IF_RULE; /* @@ -256,12 +257,23 @@ static void dict_pcre_exec_error(const char *mapname, int lineno, int errval) return; #endif default: - msg_warn("pcre map %s, line %d: unknown re_exec error: %d", + msg_warn("pcre map %s, line %d: unknown pcre_exec error: %d", mapname, lineno, errval); return; } } + /* + * Inlined to reduce function call overhead in the time-critical loop. + */ +#define DICT_PCRE_EXEC(ctxt, map, line, pattern, hints, match, str, len) \ + ((ctxt).matches = pcre_exec((pattern), (hints), (str), (len), \ + NULL_STARTOFFSET, NULL_EXEC_OPTIONS, \ + (ctxt).offsets, PCRE_MAX_CAPTURE * 3), \ + (ctxt).matches > 0 ? (match) : \ + (ctxt).matches == PCRE_ERROR_NOMATCH ? !(match) : \ + (dict_pcre_exec_error((map), (line), (ctxt).matches), 0)) + /* dict_pcre_lookup - match string and perform optional substitution */ static const char *dict_pcre_lookup(DICT *dict, const char *lookup_string) @@ -272,7 +284,6 @@ static const char *dict_pcre_lookup(DICT *dict, const char *lookup_string) DICT_PCRE_MATCH_RULE *match_rule; int lookup_len = strlen(lookup_string); DICT_PCRE_EXPAND_CONTEXT ctxt; - int nesting = 0; dict->error = 0; @@ -290,12 +301,6 @@ static const char *dict_pcre_lookup(DICT *dict, const char *lookup_string) } for (rule = dict_pcre->head; rule; rule = rule->next) { - /* - * Skip rules inside failed IF/ENDIF. - */ - if (nesting < rule->nesting) - continue; - switch (rule->op) { /* @@ -303,22 +308,10 @@ static const char *dict_pcre_lookup(DICT *dict, const char *lookup_string) */ case DICT_PCRE_OP_MATCH: match_rule = (DICT_PCRE_MATCH_RULE *) rule; - ctxt.matches = pcre_exec(match_rule->pattern, match_rule->hints, - lookup_string, lookup_len, - NULL_STARTOFFSET, NULL_EXEC_OPTIONS, - ctxt.offsets, PCRE_MAX_CAPTURE * 3); - - if (ctxt.matches > 0) { - if (!match_rule->match) - continue; /* Negative rule matched */ - } else if (ctxt.matches == PCRE_ERROR_NOMATCH) { - if (match_rule->match) - continue; /* Positive rule did not - * match */ - } else { - dict_pcre_exec_error(dict->name, rule->lineno, ctxt.matches); - continue; /* pcre_exec failed */ - } + if (!DICT_PCRE_EXEC(ctxt, dict->name, rule->lineno, + match_rule->pattern, match_rule->hints, + match_rule->match, lookup_string, lookup_len)) + continue; /* * Skip $number substitutions when the replacement text contains @@ -354,30 +347,19 @@ static const char *dict_pcre_lookup(DICT *dict, const char *lookup_string) */ case DICT_PCRE_OP_IF: if_rule = (DICT_PCRE_IF_RULE *) rule; - ctxt.matches = pcre_exec(if_rule->pattern, if_rule->hints, - lookup_string, lookup_len, - NULL_STARTOFFSET, NULL_EXEC_OPTIONS, - ctxt.offsets, PCRE_MAX_CAPTURE * 3); - - if (ctxt.matches > 0) { - if (!if_rule->match) - continue; /* Negative rule matched */ - } else if (ctxt.matches == PCRE_ERROR_NOMATCH) { - if (if_rule->match) - continue; /* Positive rule did not - * match */ - } else { - dict_pcre_exec_error(dict->name, rule->lineno, ctxt.matches); - continue; /* pcre_exec failed */ - } - nesting++; - continue; + if (DICT_PCRE_EXEC(ctxt, dict->name, rule->lineno, + if_rule->pattern, if_rule->hints, + if_rule->match, lookup_string, lookup_len)) + continue; + /* An IF without matching ENDIF has no "endif" rule. */ + if ((rule = if_rule->endif_rule) == 0) + break; + /* FALLTHROUGH */ /* - * ENDIF after successful IF. + * ENDIF after IF. */ case DICT_PCRE_OP_ENDIF: - nesting--; continue; default: @@ -588,15 +570,12 @@ static int dict_pcre_compile(const char *mapname, int lineno, /* dict_pcre_rule_alloc - fill in a generic rule structure */ -static DICT_PCRE_RULE *dict_pcre_rule_alloc(int op, int nesting, - int lineno, - size_t size) +static DICT_PCRE_RULE *dict_pcre_rule_alloc(int op, int lineno, size_t size) { DICT_PCRE_RULE *rule; rule = (DICT_PCRE_RULE *) mymalloc(size); rule->op = op; - rule->nesting = nesting; rule->lineno = lineno; rule->next = 0; @@ -704,7 +683,7 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno, * Save the result. */ match_rule = (DICT_PCRE_MATCH_RULE *) - dict_pcre_rule_alloc(DICT_PCRE_OP_MATCH, nesting, lineno, + dict_pcre_rule_alloc(DICT_PCRE_OP_MATCH, lineno, sizeof(DICT_PCRE_MATCH_RULE)); match_rule->match = regexp.match; match_rule->max_sub = prescan_context.max_sub; @@ -757,7 +736,7 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno, * Save the result. */ if_rule = (DICT_PCRE_IF_RULE *) - dict_pcre_rule_alloc(DICT_PCRE_OP_IF, nesting, lineno, + dict_pcre_rule_alloc(DICT_PCRE_OP_IF, lineno, sizeof(DICT_PCRE_IF_RULE)); if_rule->match = regexp.match; if_rule->pattern = engine.pattern; @@ -794,7 +773,7 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno, /* * Save the result. */ - rule = dict_pcre_rule_alloc(DICT_PCRE_OP_ENDIF, nesting, lineno, + rule = dict_pcre_rule_alloc(DICT_PCRE_OP_ENDIF, lineno, sizeof(DICT_PCRE_RULE)); return (rule); } @@ -813,6 +792,7 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno, DICT *dict_pcre_open(const char *mapname, int open_flags, int dict_flags) { + const char myname[] = "dict_pcre_open"; DICT_PCRE *dict_pcre; VSTREAM *map_fp = 0; struct stat st; @@ -823,6 +803,8 @@ DICT *dict_pcre_open(const char *mapname, int open_flags, int dict_flags) int lineno; int nesting = 0; char *p; + DICT_PCRE_RULE **rule_stack = 0; + MVECT mvect; /* * Let the optimizer worry about eliminating redundant code. @@ -887,9 +869,25 @@ DICT *dict_pcre_open(const char *mapname, int open_flags, int dict_flags) if (rule == 0) continue; if (rule->op == DICT_PCRE_OP_IF) { + if (rule_stack == 0) + rule_stack = (DICT_PCRE_RULE **) mvect_alloc(&mvect, + sizeof(*rule_stack), nesting + 1, + (MVECT_FN) 0, (MVECT_FN) 0); + else + rule_stack = + (DICT_PCRE_RULE **) mvect_realloc(&mvect, nesting + 1); + rule_stack[nesting] = rule; nesting++; } else if (rule->op == DICT_PCRE_OP_ENDIF) { - nesting--; + DICT_PCRE_IF_RULE *if_rule; + + if (nesting-- <= 0) + msg_panic("%s: ENDIF without IF", myname); + if (rule_stack[nesting]->op != DICT_PCRE_OP_IF) + msg_panic("%s: unexpected rule stack element type %d", + myname, rule_stack[nesting]->op); + if_rule = (DICT_PCRE_IF_RULE *) rule_stack[nesting]; + if_rule->endif_rule = rule; } if (last_rule == 0) dict_pcre->head = rule; @@ -898,9 +896,12 @@ DICT *dict_pcre_open(const char *mapname, int open_flags, int dict_flags) last_rule = rule; } - if (nesting) - msg_warn("pcre map %s, line %d: more IFs than ENDIFs", - mapname, lineno); + while (nesting-- > 0) + msg_warn("pcre map %s, line %d: IF has no matching ENDIF", + mapname, rule_stack[nesting]->lineno); + + if (rule_stack) + (void) mvect_free(&mvect); DICT_PCRE_OPEN_RETURN(DICT_DEBUG (&dict_pcre->dict)); } diff --git a/postfix/src/util/dict_pcre.map b/postfix/src/util/dict_pcre.map index f646a1f3b..7a6cefb6f 100644 --- a/postfix/src/util/dict_pcre.map +++ b/postfix/src/util/dict_pcre.map @@ -20,3 +20,8 @@ endif endif # trailing whitespace above ! +# dangling endif and if +endif +endif +if /./ +if /./ diff --git a/postfix/src/util/dict_pcre.ref b/postfix/src/util/dict_pcre.ref index 29e9dfb5f..ca008ed86 100644 --- a/postfix/src/util/dict_pcre.ref +++ b/postfix/src/util/dict_pcre.ref @@ -6,6 +6,10 @@ ./dict_open: warning: pcre map dict_pcre.map, line 10: out of range replacement index "5": skipping this rule ./dict_open: warning: pcre map dict_pcre.map, line 17: $number found in negative match replacement text: skipping this rule ./dict_open: warning: pcre map dict_pcre.map, line 22: no regexp: skipping this rule +./dict_open: warning: pcre map dict_pcre.map, line 23: ignoring ENDIF without matching IF +./dict_open: warning: pcre map dict_pcre.map, line 24: ignoring ENDIF without matching IF +./dict_open: warning: pcre map dict_pcre.map, line 26: IF has no matching ENDIF +./dict_open: warning: pcre map dict_pcre.map, line 25: IF has no matching ENDIF owner=untrusted (uid=USER) > get true true: not found diff --git a/postfix/src/util/dict_regexp.c b/postfix/src/util/dict_regexp.c index 429b12b29..953756bf2 100644 --- a/postfix/src/util/dict_regexp.c +++ b/postfix/src/util/dict_regexp.c @@ -62,6 +62,7 @@ #include "dict_regexp.h" #include "mac_parse.h" #include "warn_stat.h" +#include "mvect.h" /* * Support for IF/ENDIF based on an idea by Bert Driehuis. @@ -84,7 +85,6 @@ typedef struct { */ typedef struct DICT_REGEXP_RULE { int op; /* DICT_REGEXP_OP_MATCH/IF/ENDIF */ - int nesting; /* Level of search nesting */ int lineno; /* source file line number */ struct DICT_REGEXP_RULE *next; /* next rule in dict */ } DICT_REGEXP_RULE; @@ -103,6 +103,7 @@ typedef struct { DICT_REGEXP_RULE rule; /* generic members */ regex_t *expr; /* the condition */ int match; /* positive or negative match */ + struct DICT_REGEXP_RULE *endif_rule;/* matching endif rule */ } DICT_REGEXP_IF_RULE; /* @@ -216,7 +217,6 @@ static const char *dict_regexp_lookup(DICT *dict, const char *lookup_string) DICT_REGEXP_MATCH_RULE *match_rule; DICT_REGEXP_EXPAND_CONTEXT expand_context; int error; - int nesting = 0; dict->error = 0; @@ -234,12 +234,6 @@ static const char *dict_regexp_lookup(DICT *dict, const char *lookup_string) } for (rule = dict_regexp->head; rule; rule = rule->next) { - /* - * Skip rules inside failed IF/ENDIF. - */ - if (nesting < rule->nesting) - continue; - switch (rule->op) { /* @@ -301,14 +295,16 @@ static const char *dict_regexp_lookup(DICT *dict, const char *lookup_string) if (DICT_REGEXP_REGEXEC(error, dict->name, rule->lineno, if_rule->expr, if_rule->match, lookup_string, NULL_SUBSTITUTIONS, NULL_MATCH_RESULT)) - nesting++; - continue; + continue; + /* An IF without matching ENDIF has no "endif" rule. */ + if ((rule = if_rule->endif_rule) == 0) + break; + /* FALLTHROUGH */ /* - * ENDIF after successful IF. + * ENDIF after IF. */ case DICT_REGEXP_OP_ENDIF: - nesting--; continue; default: @@ -534,15 +530,12 @@ static regex_t *dict_regexp_compile_pat(const char *mapname, int lineno, /* dict_regexp_rule_alloc - fill in a generic rule structure */ -static DICT_REGEXP_RULE *dict_regexp_rule_alloc(int op, int nesting, - int lineno, - size_t size) +static DICT_REGEXP_RULE *dict_regexp_rule_alloc(int op, int lineno, size_t size) { DICT_REGEXP_RULE *rule; rule = (DICT_REGEXP_RULE *) mymalloc(size); rule->op = op; - rule->nesting = nesting; rule->lineno = lineno; rule->next = 0; @@ -656,7 +649,7 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno, second_exp = 0; } match_rule = (DICT_REGEXP_MATCH_RULE *) - dict_regexp_rule_alloc(DICT_REGEXP_OP_MATCH, nesting, lineno, + dict_regexp_rule_alloc(DICT_REGEXP_OP_MATCH, lineno, sizeof(DICT_REGEXP_MATCH_RULE)); match_rule->first_exp = first_exp; match_rule->first_match = first_pat.match; @@ -694,7 +687,7 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno, if ((expr = dict_regexp_compile_pat(mapname, lineno, &pattern)) == 0) return (0); if_rule = (DICT_REGEXP_IF_RULE *) - dict_regexp_rule_alloc(DICT_REGEXP_OP_IF, nesting, lineno, + dict_regexp_rule_alloc(DICT_REGEXP_OP_IF, lineno, sizeof(DICT_REGEXP_IF_RULE)); if_rule->expr = expr; if_rule->match = pattern.match; @@ -718,7 +711,7 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno, if (*p) msg_warn("regexp map %s, line %d: ignoring extra text after ENDIF", mapname, lineno); - rule = dict_regexp_rule_alloc(DICT_REGEXP_OP_ENDIF, nesting, lineno, + rule = dict_regexp_rule_alloc(DICT_REGEXP_OP_ENDIF, lineno, sizeof(DICT_REGEXP_RULE)); return (rule); } @@ -737,6 +730,7 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno, DICT *dict_regexp_open(const char *mapname, int open_flags, int dict_flags) { + const char myname[] = "dict_regexp_open"; DICT_REGEXP *dict_regexp; VSTREAM *map_fp = 0; struct stat st; @@ -748,6 +742,8 @@ DICT *dict_regexp_open(const char *mapname, int open_flags, int dict_flags) size_t max_sub = 0; int nesting = 0; char *p; + DICT_REGEXP_RULE **rule_stack = 0; + MVECT mvect; /* * Let the optimizer worry about eliminating redundant code. @@ -810,9 +806,25 @@ DICT *dict_regexp_open(const char *mapname, int open_flags, int dict_flags) if (((DICT_REGEXP_MATCH_RULE *) rule)->max_sub > max_sub) max_sub = ((DICT_REGEXP_MATCH_RULE *) rule)->max_sub; } else if (rule->op == DICT_REGEXP_OP_IF) { + if (rule_stack == 0) + rule_stack = (DICT_REGEXP_RULE **) mvect_alloc(&mvect, + sizeof(*rule_stack), nesting + 1, + (MVECT_FN) 0, (MVECT_FN) 0); + else + rule_stack = + (DICT_REGEXP_RULE **) mvect_realloc(&mvect, nesting + 1); + rule_stack[nesting] = rule; nesting++; } else if (rule->op == DICT_REGEXP_OP_ENDIF) { - nesting--; + DICT_REGEXP_IF_RULE *if_rule; + + if (nesting-- <= 0) + msg_panic("%s: ENDIF without IF", myname); + if (rule_stack[nesting]->op != DICT_REGEXP_OP_IF) + msg_panic("%s: unexpected rule stack element type %d", + myname, rule_stack[nesting]->op); + if_rule = (DICT_REGEXP_IF_RULE *) rule_stack[nesting]; + if_rule->endif_rule = rule; } if (last_rule == 0) dict_regexp->head = rule; @@ -821,9 +833,12 @@ DICT *dict_regexp_open(const char *mapname, int open_flags, int dict_flags) last_rule = rule; } - if (nesting) - msg_warn("regexp map %s, line %d: more IFs than ENDIFs", - mapname, lineno); + while (nesting-- > 0) + msg_warn("regexp map %s, line %d: IF has no matching ENDIF", + mapname, rule_stack[nesting]->lineno); + + if (rule_stack) + (void) mvect_free(&mvect); /* * Allocate space for only as many matched substrings as used in the diff --git a/postfix/src/util/dict_regexp.map b/postfix/src/util/dict_regexp.map index f646a1f3b..7a6cefb6f 100644 --- a/postfix/src/util/dict_regexp.map +++ b/postfix/src/util/dict_regexp.map @@ -20,3 +20,8 @@ endif endif # trailing whitespace above ! +# dangling endif and if +endif +endif +if /./ +if /./ diff --git a/postfix/src/util/dict_regexp.ref b/postfix/src/util/dict_regexp.ref index 589300dc2..7b5bc88a9 100644 --- a/postfix/src/util/dict_regexp.ref +++ b/postfix/src/util/dict_regexp.ref @@ -5,6 +5,11 @@ ./dict_open: warning: regexp map dict_regexp.map, line 10: out of range replacement index "5": skipping this rule ./dict_open: warning: regexp map dict_regexp.map, line 17: $number found in negative match replacement text: skipping this rule ./dict_open: warning: regexp map dict_regexp.map, line 22: no regexp: skipping this rule +./dict_open: warning: regexp map dict_regexp.map, line 24: ignoring ENDIF without matching IF +./dict_open: warning: regexp map dict_regexp.map, line 25: ignoring ENDIF without matching IF +./dict_open: warning: regexp map dict_regexp.map, line 27: IF has no matching ENDIF +./dict_open: warning: regexp map dict_regexp.map, line 26: IF has no matching ENDIF +owner=untrusted (uid=USER) > get true true: not found > get true1 diff --git a/postfix/src/util/mvect.c b/postfix/src/util/mvect.c index 346b8e0ba..3353799f3 100644 --- a/postfix/src/util/mvect.c +++ b/postfix/src/util/mvect.c @@ -108,6 +108,5 @@ char *mvect_free(MVECT *vect) if (vect->wipe_fn) vect->wipe_fn(vect->ptr, vect->nelm); myfree(vect->ptr); - myfree((void *) vect); return (0); }