]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.2-20160522
authorWietse Venema <wietse@porcupine.org>
Sun, 22 May 2016 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Thu, 26 May 2016 01:13:03 +0000 (21:13 -0400)
postfix/HISTORY
postfix/WISHLIST
postfix/src/global/mail_version.h
postfix/src/util/Makefile.in
postfix/src/util/dict_pcre.c
postfix/src/util/dict_pcre.map
postfix/src/util/dict_pcre.ref
postfix/src/util/dict_regexp.c
postfix/src/util/dict_regexp.map
postfix/src/util/dict_regexp.ref
postfix/src/util/mvect.c

index 52f161c22f6f7194df1f66d19f17258936ab1bbe..4d58b31efddde95e155cc3c4cc2135e0977f5f0a 100644 (file)
@@ -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.
index 3e97c23636b536b27a6321d2581a3349ffcdf66e..44eb73c831c67024879c0e865540bf980f19deda 100644 (file)
@@ -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
index a749bf2f96681fb7a4ac43ff994a3bdf8acee6f2..c5e9d73461e2342e03b88c16b1fc9d21ae1b19ac 100644 (file)
@@ -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
index cf2fe179f382cb7c1032178dba4979ddfe735a10..f1c5b8079ebbfc0db215bb92f5d8b8dab31dcecf 100644 (file)
@@ -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.in | sed 's/uid=[0-9][0-9][0-9]*/uid=USER/' >dict_regexp.tmp
+       $(SHLIB_ENV) ./dict_open regexp:dict_regexp.map read <dict_regexp.in 2>&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
index fe388c2a2c20c3015649835c431d646d64f7cf7c..17c500d286aef1876b93815e0adf9a638814d64b 100644 (file)
@@ -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));
 }
index f646a1f3b52354e737e3902dd0e298b84d80d455..7a6cefb6f84e9aa5ef7f6b4a406c078eb6502aba 100644 (file)
@@ -20,3 +20,8 @@ endif
 endif   
 # trailing whitespace above
 !
+# dangling endif and if
+endif
+endif
+if /./
+if /./
index 29e9dfb5fae42ba1431f1a9165ef66c2be998b9c..ca008ed86576bbc69ca441583b6a152adf251404 100644 (file)
@@ -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
index 429b12b29748f887a0618f1cc79fff3f935e5295..953756bf2fad0f37829b4a5c86e7de051598d6b6 100644 (file)
@@ -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
index f646a1f3b52354e737e3902dd0e298b84d80d455..7a6cefb6f84e9aa5ef7f6b4a406c078eb6502aba 100644 (file)
@@ -20,3 +20,8 @@ endif
 endif   
 # trailing whitespace above
 !
+# dangling endif and if
+endif
+endif
+if /./
+if /./
index 589300dc218862f1da0d14a79afaaa01ed896416..7b5bc88a9c281627f233a0f3e4d7008d130d2af4 100644 (file)
@@ -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
index 346b8e0baef98e0b0c42115a8411411111d7a78e..3353799f3d28688dbddc438ce85e6c9b985da14a 100644 (file)
@@ -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);
 }