]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.7-20211127
authorWietse Venema <wietse@porcupine.org>
Sat, 27 Nov 2021 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Wed, 19 Jan 2022 06:36:07 +0000 (01:36 -0500)
18 files changed:
postfix/HISTORY
postfix/README_FILES/PCRE_README
postfix/RELEASE_NOTES
postfix/WISHLIST
postfix/html/PCRE_README.html
postfix/html/makedefs.1.html
postfix/html/pcre_table.5.html
postfix/makedefs
postfix/man/man1/makedefs.1
postfix/man/man5/pcre_table.5
postfix/proto/PCRE_README.html
postfix/proto/pcre_table
postfix/src/global/mail_version.h
postfix/src/postcat/postcat.c
postfix/src/util/Makefile.in
postfix/src/util/dict_pcre.c
postfix/src/util/dict_pcre.map
postfix/src/util/dict_pcre.ref

index 3824d470b5a28efd3266fb9230f5825e4be74cf1..819847677e5f50c15af5437d97ede1531c20943e 100644 (file)
@@ -25929,3 +25929,10 @@ Apologies for any names omitted.
 
        Regression prevention: copied a queue file record typecheck
        from the pickup daemon. Files: *qmgr/qmgr_message.c.
+
+20211127
+
+       Feature: support for the pcre2 library (the legacy pcre
+       library is still supported). See RELEASE_NOTES for details.
+       Files: makedefs, util/dict_open.c, util.dict_pcre.c,
+       proto/pcre_table, proto/PCRE_README.html.
index 788859a5e9689636767bdab77b7c5c6d9634c7a8..d8bf8d5046fdd954f78d2b2b1bd6e5a07451692e 100644 (file)
@@ -14,33 +14,42 @@ A description of how to use pcre tables, including examples, is given in the
 pcre_table(5) manual page. Information about PCRE itself can be found at http:/
 /www.pcre.org/.
 
-B\bBu\bui\bil\bld\bdi\bin\bng\bg P\bPo\bos\bst\btf\bfi\bix\bx w\bwi\bit\bth\bh P\bPC\bCR\bRE\bE s\bsu\bup\bpp\bpo\bor\brt\bt
+U\bUs\bsi\bin\bng\bg P\bPo\bos\bst\btf\bfi\bix\bx p\bpa\bac\bck\bka\bag\bge\bes\bs w\bwi\bit\bth\bh P\bPC\bCR\bRE\bE s\bsu\bup\bpp\bpo\bor\brt\bt
+
+To use pcre with Debian GNU/Linux's Postfix, or with Fedora or RHEL Postfix,
+all you need is to install the postfix-pcre package and you're done. There is
+no need to recompile Postfix.
+
+B\bBu\bui\bil\bld\bdi\bin\bng\bg P\bPo\bos\bst\btf\bfi\bix\bx f\bfr\bro\bom\bm s\bso\bou\bur\brc\bce\be w\bwi\bit\bth\bh P\bPC\bCR\bRE\bE s\bsu\bup\bpp\bpo\bor\brt\bt
 
 These instructions assume that you build Postfix from source code as described
-in the INSTALL document. Some modification may be required if you build Postfix
-from a vendor-specific source package.
+in the INSTALL document.
 
-Note: to use pcre with Debian GNU/Linux's Postfix, all you need is to install
-the postfix-pcre package and you're done. There is no need to recompile
-Postfix.
+To build Postfix from source with pcre support, you need a pcre library.
+Install a vendor package, or download the source code from locations in https:/
+/www.pcre.org/ and build that yourself.
 
-In some future, Postfix will have a plug-in interface for adding map types.
-Until then, you need to compile PCRE support into Postfix.
+Postfix can build with the pcre2 library or the legacy pcre library. It's
+probably easiest to let the Postfix build procedure pick one. The following
+commands will first discover if the pcre2 library is installed, and if that is
+not available, will discover if the legacy pcre library is installed.
 
-First of all, you need the PCRE library (Perl Compatible Regular Expressions),
-which can be obtained from:
+    $ make -f Makefile.init makefiles
+    $ make
 
-    ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/.
+To build Postfix explicitly with a pcre2 library (Postfix 3.7 and later):
 
-NOTE: pcre versions prior to 2.06 cannot be used.
+    $ make -f Makefile.init makefiles \
+        "CCARGS=-DHAS_PCRE=2 `pcre2-config --cflags`" \
+        "AUXLIBS_PCRE=`pcre2-config --libs`"
+    $ make
 
-In order to build Postfix with PCRE support you need to add -DHAS_PCRE and a -
-I option for the PCRE include file to CCARGS, and add the path to the PCRE
-library to AUXLIBS_PCRE, for example:
+To build Postfix explicitly with a legacy pcre library (all Postfix versions):
 
-    make -f Makefile.init makefiles \
-        "CCARGS=-DHAS_PCRE `pcre-config --cflags`" \
+    make -f Makefile.init makefiles \
+        "CCARGS=-DHAS_PCRE=1 `pcre-config --cflags`" \
         "AUXLIBS_PCRE=`pcre-config --libs`"
+    $ make
 
 Postfix versions before 3.0 use AUXLIBS instead of AUXLIBS_PCRE. With Postfix
 3.0 and later, the old AUXLIBS variable still supports building a statically-
index ef4e4c9db20f28f0a39501494909022cba2f841f..fc07144fc07374e20c3b9171a6976b32c005c635 100644 (file)
@@ -25,6 +25,18 @@ more recent Eclipse Public License 2.0. Recipients can choose to take
 the software under the license of their choice. Those who are more
 comfortable with the IPL can continue with that license.
 
+Major changes with snapshot 20211127
+====================================
+
+Support for the pcre2 library (the legacy pcre library is no longer
+maintained). The Postfix build procedure automatically detects if
+the pcre2 library is installed, and if it is unavailable, the Postfix
+build procedure will detect if the legacy pcre library is installed.
+See PCRE_README if you need to build Postfix with a specific library.
+
+Visible differences: some error messages may have a different text,
+and the 'X' pattern flag is no longer supported with pcre2.
+
 Major changes with snapshot 20210815
 ====================================
 
index 0985ec0343bd15c91b935b7b739bacc30b50b60d..3801c64e568b6e933349a9560f4a1a6a9b4e1432 100644 (file)
@@ -1,5 +1,12 @@
 Wish list:
 
+       Convert the proxymap protol into "server speaks first".
+
+       Fix code that still uses "long" for data_size and data_offset,
+       and that uses "%ld" in sscanf().
+
+       A smart query services for live Postfix tables that outputs JSON?
+
        proxy_read_maps needs a dedicated matcher that looks
        inside pipemap:{}. Maybe steal some code from postconf.
 
index 103bbe8cb4844337308e72af9b2c418309756a22..810e3aad070cbf65426db5a605f018f82fdefb40 100644 (file)
@@ -30,39 +30,56 @@ expression implementation that you find on many systems. </p>
 is given in the <a href="pcre_table.5.html">pcre_table(5)</a> manual page. Information about PCRE
 itself can be found at <a href="http://www.pcre.org/">http://www.pcre.org/</a>. </p>
 
-<h2>Building Postfix with PCRE support</h2>
+<h2>Using Postfix packages with PCRE support</h2>
 
-<p> These instructions assume that you build Postfix from source
-code as described in the <a href="INSTALL.html">INSTALL</a> document. Some modification may
-be required if you build Postfix from a vendor-specific source
-package.  </p>
-
-<p> Note: to use pcre with Debian GNU/Linux's Postfix, all you
+<p> To use pcre with Debian GNU/Linux's Postfix, or with Fedora or
+RHEL Postfix, all you
 need is to install the postfix-pcre package and you're done.  There
 is no need to recompile Postfix. </p>
 
-<p> In some future, Postfix will have a plug-in interface for adding
-map types. Until then, you need to compile PCRE support into Postfix.
-</p>
+<h2>Building Postfix from source with PCRE support</h2>
 
-<p> First of all, you need the PCRE library (Perl Compatible Regular
-Expressions), which can be obtained from: </p>
+<p> These instructions assume that you build Postfix from source
+code as described in the <a href="INSTALL.html">INSTALL</a> document. </p>
 
-<blockquote> 
-<a href="ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/">ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/</a>.
+<p> To build Postfix from source with pcre support, you need a pcre
+library. Install a vendor package, or download the source code from
+locations in <a href="https://www.pcre.org/">https://www.pcre.org/</a> and build that yourself.
+
+<p> Postfix can build with the pcre2 library or the legacy pcre
+library. It's probably easiest to let the Postfix build procedure
+pick one. The following commands will first discover if the pcre2
+library is installed, and if that is not available, will discover
+if the legacy pcre library is installed. </p>
+
+<blockquote>
+<pre>
+$ make -f Makefile.init makefiles 
+$ make
+</pre>
 </blockquote>
 
-<p> NOTE: pcre versions prior to 2.06 cannot be used. </p>
+<p> To build Postfix explicitly with a pcre2 library (Postfix 3.7
+and later): </p>
+
+<blockquote>
+<pre>
+$ make -f Makefile.init makefiles \
+    "CCARGS=-DHAS_PCRE=2 `pcre2-config --cflags`" \
+    "<a href="PCRE_README.html">AUXLIBS_PCRE</a>=`pcre2-config --libs`"
+$ make
+</pre>
+</blockquote>
 
-<p> In order to build Postfix with PCRE support you need to add
--DHAS_PCRE and a -I option for the PCRE include file to CCARGS, and
-add the path to the PCRE library to <a href="PCRE_README.html">AUXLIBS_PCRE</a>, for example: </p>
+<p> To build Postfix explicitly with a legacy pcre library (all
+Postfix versions): </p>
 
 <blockquote>
 <pre>
-make -f Makefile.init makefiles \
-    "CCARGS=-DHAS_PCRE `pcre-config --cflags`" \
+make -f Makefile.init makefiles \
+    "CCARGS=-DHAS_PCRE=1 `pcre-config --cflags`" \
     "<a href="PCRE_README.html">AUXLIBS_PCRE</a>=`pcre-config --libs`"
+$ make
 </pre>
 </blockquote>
 
index ec47830713382e18e01757f9af1485971f06a66d..008787d1939e1952e0de841d70d23e8f21e5d232 100644 (file)
@@ -104,7 +104,8 @@ MAKEDEFS(1)                                                        MAKEDEFS(1)
 
               <b>-DNO_PCRE</b>
                      Do not build with PCRE support.  By default, PCRE support
-                     is compiled in when the <b>pcre-config</b> utility is installed.
+                     is compiled in when the <b>pcre2-config</b> or <b>pcre-config</b> util-
+                     ity are installed.
 
               <b>-DNO_POSIX_GETPW_R</b>
                      Disable support for POSIX getpwnam_r/getpwuid_r.
index b692fcff7fe92f7468646f9970adca7dfbab1876..7a3f3b7379ddb3d9a66be0aaae830aef841aac9c 100644 (file)
@@ -36,8 +36,11 @@ PCRE_TABLE(5)                                                    PCRE_TABLE(5)
        terns,  and  "<b>postmap -bmq -</b> &lt;<i>file</i>" for <a href="header_checks.5.html">body_checks(5)</a> (Postfix 2.6 and
        later).
 
+       This driver can be built  with  the  pcre2  library  (Postfix  3.7  and
+       later), or with the legacy pcre library (all Postfix versions).
+
 <b>COMPATIBILITY</b>
-       With Postfix version 2.2 and earlier specify "<b>postmap -fq</b>" to  query  a
+       With  Postfix  version 2.2 and earlier specify "<b>postmap -fq</b>" to query a
        table that contains case sensitive patterns. Patterns are case insensi-
        tive by default.
 
@@ -45,16 +48,16 @@ PCRE_TABLE(5)                                                    PCRE_TABLE(5)
        The general form of a PCRE table is:
 
        <b>/</b><i>pattern</i><b>/</b><i>flags result</i>
-              When <i>pattern</i> matches the input  string,  use  the  corresponding
+              When  <i>pattern</i>  matches  the  input string, use the corresponding
               <i>result</i> value.
 
        <b>!/</b><i>pattern</i><b>/</b><i>flags result</i>
-              When  <i>pattern</i>  does  <b>not</b>  match the input string, use the corre-
+              When <i>pattern</i> does <b>not</b> match the input  string,  use  the  corre-
               sponding <i>result</i> value.
 
        <b>if /</b><i>pattern</i><b>/</b><i>flags</i>
 
-       <b>endif</b>  If the input string matches /<i>pattern</i>/,  then  match  that  input
+       <b>endif</b>  If  the  input  string  matches /<i>pattern</i>/, then match that input
               string against the patterns between <b>if</b> and <b>endif</b>.  The <b>if</b>..<b>endif</b>
               can nest.
 
@@ -64,8 +67,8 @@ PCRE_TABLE(5)                                                    PCRE_TABLE(5)
 
        <b>if !/</b><i>pattern</i><b>/</b><i>flags</i>
 
-       <b>endif</b>  If the input string does not match /<i>pattern</i>/,  then  match  that
-              input  string  against  the  patterns  between <b>if</b> and <b>endif</b>. The
+       <b>endif</b>  If  the  input  string does not match /<i>pattern</i>/, then match that
+              input string against the patterns  between  <b>if</b>  and  <b>endif</b>.  The
               <b>if</b>..<b>endif</b> can nest.
 
               Note: do not prepend whitespace to patterns inside <b>if</b>..<b>endif</b>.
@@ -73,92 +76,95 @@ PCRE_TABLE(5)                                                    PCRE_TABLE(5)
               This feature is available in Postfix 2.1 and later.
 
        blank lines and comments
-              Empty lines and whitespace-only lines are ignored, as are  lines
+              Empty  lines and whitespace-only lines are ignored, as are lines
               whose first non-whitespace character is a `#'.
 
        multi-line text
-              A  logical  line  starts  with  non-whitespace text. A line that
+              A logical line starts with  non-whitespace  text.  A  line  that
               starts with whitespace continues a logical line.
 
-       Each pattern is a perl-like regular expression. The  expression  delim-
-       iter  can  be  any  non-alphanumerical  character, except whitespace or
-       characters that have special meaning (traditionally the  forward  slash
-       is used).  The regular expression can contain whitespace.
+       Each  pattern  is a perl-like regular expression. The expression delim-
+       iter can be any non-alphanumeric character, except whitespace or  char-
+       acters  that  have  special meaning (traditionally the forward slash is
+       used).  The regular expression can contain whitespace.
 
-       By  default, matching is case-insensitive, and newlines are not treated
-       as special characters. The behavior is controlled by flags,  which  are
-       toggled  by appending one or more of the following characters after the
+       By default, matching is case-insensitive, and newlines are not  treated
+       as  special  characters. The behavior is controlled by flags, which are
+       toggled by appending one or more of the following characters after  the
        pattern:
 
        <b>i</b> (default: on)
-              Toggles the case sensitivity flag. By default, matching is  case
+              Toggles  the case sensitivity flag. By default, matching is case
               insensitive.
 
        <b>m</b> (default: off)
-              Toggles the PCRE_MULTILINE flag. When this flag is on, the <b>^</b> and
-              <b>$</b> metacharacters match immediately after and immediately  before
-              a  newline  character,  respectively, in addition to matching at
+              Toggles the pcre MULTILINE flag. When this flag is on, the <b>^</b> and
+              <b>$</b>  metacharacters match immediately after and immediately before
+              a newline character, respectively, in addition  to  matching  at
               the start and end of the subject string.
 
        <b>s</b> (default: on)
-              Toggles the PCRE_DOTALL flag.  When  this  flag  is  on,  the  <b>.</b>
-              metacharacter  matches  the newline character. With Postfix ver-
-              sions prior to 2.0, the flag is off by default, which is  incon-
+              Toggles  the  pcre  DOTALL  flag.  When  this  flag is on, the <b>.</b>
+              metacharacter matches the newline character. With  Postfix  ver-
+              sions  prior to 2.0, the flag is off by default, which is incon-
               venient for multi-line message header matching.
 
        <b>x</b> (default: off)
               Toggles the pcre extended flag. When this flag is on, whitespace
-              characters in the pattern (other than in a character class)  are
-              ignored.   To include a whitespace character as part of the pat-
+              characters  in the pattern (other than in a character class) are
+              ignored.  To include a whitespace character as part of the  pat-
               tern, escape it with backslash.
 
               Note: do not use <b>#</b><i>comment</i> after patterns.
 
        <b>A</b> (default: off)
-              Toggles the PCRE_ANCHORED flag.  When this flag is on, the  pat-
-              tern  is  forced to be "anchored", that is, it is constrained to
-              match only at the start of the string which  is  being  searched
-              (the  "subject  string").  This  effect  can also be achieved by
+              Toggles  the pcre ANCHORED flag.  When this flag is on, the pat-
+              tern is forced to be "anchored", that is, it is  constrained  to
+              match  only  at  the start of the string which is being searched
+              (the "subject string"). This effect  can  also  be  achieved  by
               appropriate constructs in the pattern itself.
 
        <b>E</b> (default: off)
-              Toggles the PCRE_DOLLAR_ENDONLY flag. When this flag is on, a  <b>$</b>
+              Toggles  the pcre DOLLAR_ENDONLY flag. When this flag is on, a <b>$</b>
               metacharacter in the pattern matches only at the end of the sub-
-              ject string. Without this flag, a dollar  also  matches  immedi-
-              ately  before  the  final character if it is a newline character
-              (but not before any other  newline  characters).  This  flag  is
-              ignored if PCRE_MULTILINE flag is set.
+              ject  string.  Without  this flag, a dollar also matches immedi-
+              ately before the final character if it is  a  newline  character
+              (but  not  before  any  other  newline characters). This flag is
+              ignored if the pcre MULTILINE flag is set.
 
        <b>U</b> (default: off)
-              Toggles  the  ungreedy matching flag.  When this flag is on, the
-              pattern matching engine inverts the "greediness" of the  quanti-
-              fiers  so that they are not greedy by default, but become greedy
-              if followed by "?".  This flag can also set by a  (?U)  modifier
+              Toggles the pcre UNGREEDY flag.  When this flag is on, the  pat-
+              tern matching engine inverts the "greediness" of the quantifiers
+              so that they are not greedy by default,  but  become  greedy  if
+              followed  by  "?".   This  flag  can also set by a (?U) modifier
               within the pattern.
 
        <b>X</b> (default: off)
-              Toggles  the  PCRE_EXTRA  flag.  When this flag is on, any back-
+              Toggles the pcre EXTRA flag.  When this flag is  on,  any  back-
               slash in a pattern that is followed by a letter that has no spe-
-              cial  meaning causes an error, thus reserving these combinations
+              cial meaning causes an error, thus reserving these  combinations
               for future expansion.
 
+              This feature is not supported with PCRE2.
+
 <b>SEARCH ORDER</b>
-       Patterns are applied in the order as specified in the  table,  until  a
+       Patterns  are  applied  in the order as specified in the table, until a
        pattern is found that matches the input string.
 
-       Each  pattern  is applied to the entire input string.  Depending on the
+       Each pattern is applied to the entire input string.  Depending  on  the
        application, that string is an entire client hostname, an entire client
-       IP  address, or an entire mail address.  Thus, no parent domain or par-
+       IP address, or an entire mail address.  Thus, no parent domain or  par-
        ent network search is done, and <i>user@domain</i> mail addresses are not bro-
-       ken  up  into  their <i>user</i> and <i>domain</i> constituent parts, nor is <i>user+foo</i>
+       ken up into their <i>user</i> and <i>domain</i> constituent parts,  nor  is  <i>user+foo</i>
        broken up into <i>user</i> and <i>foo</i>.
 
 <b>TEXT SUBSTITUTION</b>
-       Substitution of substrings (text that  matches  patterns  inside  "()")
-       from  the  matched  expression into the result string is requested with
-       $1, $2, etc.; specify $$ to produce  a  $  character  as  output.   The
-       macros  in  the result string may need to be written as ${n} or $(n) if
-       they aren't followed by whitespace.
+       Substitution  of  substrings  (text  that matches patterns inside "()")
+       from the matched expression into the result string  is  requested  with
+       $1,  $2,  etc.;  specify  $$  to  produce a $ character as output.  The
+       macros in the result string may need to be written as ${n} or  $(n)  if
+       they  aren't  followed  by  whitespace.   This feature does not support
+       pcre2 substring names.
 
        Note: since negated patterns (those preceded by <b>!</b>) return a result when
        the  expression  does  not  match,  substitutions are not available for
index 2803397502b7ee1b04be7426b5c078b5fc00a108..0f3977c0aca0d9b37d4a17e00e7dfa13db3eea28 100644 (file)
@@ -90,8 +90,8 @@
 #      is unavailable on some recent Solaris distributions.
 # .IP \fB-DNO_PCRE\fR
 #      Do not build with PCRE support.
-#      By default, PCRE support is compiled in when the \fBpcre-config\fR
-#      utility is installed.
+#      By default, PCRE support is compiled in when the \fBpcre2-config\fR
+#      or \fBpcre-config\fR utility are installed.
 # .IP \fB-DNO_POSIX_GETPW_R\fR
 #      Disable support for POSIX getpwnam_r/getpwuid_r.
 # .IP \fB-DNO_RES_NCALLS\fR
@@ -866,11 +866,17 @@ test -r /dev/urandom && CCARGS="$CCARGS -DHAS_DEV_URANDOM"
 case "$CCARGS" in
 *-DHAS_PCRE*)  ;;
  *-DNO_PCRE*)  ;;
-          *)   pcre_cflags=`(pcre-config --cflags) 2>/dev/null` &&
-                   pcre_libs=`(pcre-config --libs) 2>/dev/null` && {
-                       CCARGS="$CCARGS -DHAS_PCRE $pcre_cflags"
-                       AUXLIBS_PCRE="$pcre_libs"
-               }
+          *)   if pcre_cflags=`(pcre2-config --cflags) 2>/dev/null` &&
+                   pcre_libs=`(pcre2-config --libs8) 2>/dev/null` 
+               then
+                   CCARGS="$CCARGS -DHAS_PCRE=2 $pcre_cflags"
+                   AUXLIBS_PCRE="$pcre_libs"
+               elif pcre_cflags=`(pcre-config --cflags) 2>/dev/null` &&
+                   pcre_libs=`(pcre-config --libs) 2>/dev/null` 
+               then
+                   CCARGS="$CCARGS -DHAS_PCRE=1 $pcre_cflags"
+                   AUXLIBS_PCRE="$pcre_libs"
+               fi
                ;;
 esac
 
@@ -1155,7 +1161,8 @@ ${WARN='-Wall -Wno-comment -Wformat -Wimplicit -Wmissing-prototypes \
 # The following was validated in 2014 on FreeBSD/Linux and Solaris 9.
 
 DEFINED_MAP_TYPES=`
-    echo $CCARGS | tr -cd '\- _ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' | 
+    echo $CCARGS | sed 's/=[^ ]*//g' | 
+       tr -cd '\- _ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' | 
        tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | ${AWK} '
        { for (n = 1; n <= NF; n++)
              if ($n ~ /^-dhas_/)
index adc2af2f94fa2cebdbc66e48ad575bdadd2feb57..70c848e0d4c0a4b16cbaefb009cc83131e41c620 100644 (file)
@@ -93,8 +93,8 @@ Do not build with NISPLUS support. Support for NISPLUS
 is unavailable on some recent Solaris distributions.
 .IP \fB\-DNO_PCRE\fR
 Do not build with PCRE support.
-By default, PCRE support is compiled in when the \fBpcre\-config\fR
-utility is installed.
+By default, PCRE support is compiled in when the \fBpcre2\-config\fR
+or \fBpcre\-config\fR utility are installed.
 .IP \fB\-DNO_POSIX_GETPW_R\fR
 Disable support for POSIX getpwnam_r/getpwuid_r.
 .IP \fB\-DNO_RES_NCALLS\fR
index b56dd09ce300a967297bd4823dcfc2ffdb87a46d..0e99721f30f692a3cf5cbd5776e876b245ae96fc 100644 (file)
@@ -35,6 +35,10 @@ as described in the SYNOPSIS above. Use "\fBpostmap \-hmq
 \-\fR <\fIfile\fR" for header_checks(5) patterns, and
 "\fBpostmap \-bmq \-\fR <\fIfile\fR" for body_checks(5)
 (Postfix 2.6 and later).
+
+This driver can be built with the pcre2 library (Postfix
+3.7 and later), or with the legacy pcre library (all Postfix
+versions).
 .SH "COMPATIBILITY"
 .na
 .nf
@@ -83,7 +87,7 @@ A logical line starts with non\-whitespace text. A line that
 starts with whitespace continues a logical line.
 .PP
 Each pattern is a perl\-like regular expression. The expression
-delimiter can be any non\-alphanumerical character, except
+delimiter can be any non\-alphanumeric character, except
 whitespace or characters
 that have special meaning (traditionally the forward slash is used).
 The regular expression can contain whitespace.
@@ -96,12 +100,12 @@ characters after the pattern:
 Toggles the case sensitivity flag. By default, matching is case
 insensitive.
 .IP "\fBm\fR (default: off)"
-Toggles the PCRE_MULTILINE flag. When this flag is on, the \fB^\fR
+Toggles the pcre MULTILINE flag. When this flag is on, the \fB^\fR
 and \fB$\fR metacharacters match immediately after and immediately
 before a newline character, respectively, in addition to
 matching at the start and end of the subject string.
 .IP "\fBs\fR (default: on)"
-Toggles the PCRE_DOTALL flag. When this flag is on, the \fB.\fR
+Toggles the pcre DOTALL flag. When this flag is on, the \fB.\fR
 metacharacter matches the newline character. With
 Postfix versions prior to 2.0, the flag is off by
 default, which is inconvenient for multi\-line message header
@@ -114,31 +118,33 @@ the pattern, escape it with backslash.
 .sp
 Note: do not use \fB#\fIcomment\fR after patterns.
 .IP "\fBA\fR (default: off)"
-Toggles the PCRE_ANCHORED flag.  When this flag is on,
+Toggles the pcre ANCHORED flag.  When this flag is on,
 the pattern is forced to be "anchored", that is, it is
 constrained to match only at the start of the string which
 is being searched (the "subject string"). This effect can
 also be achieved by appropriate constructs in the pattern
 itself.
 .IP "\fBE\fR (default: off)"
-Toggles the PCRE_DOLLAR_ENDONLY flag. When this flag is on,
+Toggles the pcre DOLLAR_ENDONLY flag. When this flag is on,
 a \fB$\fR metacharacter in the pattern matches only at the
 end of the subject string. Without this flag, a dollar also
 matches immediately before the final character if it is a
 newline character (but not before any other newline
-characters). This flag is ignored if PCRE_MULTILINE
+characters). This flag is ignored if the pcre MULTILINE
 flag is set.
 .IP "\fBU\fR (default: off)"
-Toggles the ungreedy matching flag.  When this flag is on,
+Toggles the pcre UNGREEDY flag.  When this flag is on,
 the pattern matching engine inverts the "greediness" of
 the quantifiers so that they are not greedy by default,
 but become greedy if followed by "?".  This flag can also
 set by a (?U) modifier within the pattern.
 .IP "\fBX\fR (default: off)"
-Toggles the PCRE_EXTRA flag.
+Toggles the pcre EXTRA flag.
 When this flag is on, any backslash in a pattern that is
 followed by a letter that has no special meaning causes an
 error, thus reserving these combinations for future expansion.
+
+This feature is not supported with PCRE2.
 .SH "SEARCH ORDER"
 .na
 .nf
@@ -165,6 +171,7 @@ string is requested with $1, $2, etc.; specify $$ to produce
 a $ character as output.
 The macros in the result string may need to be written as
 ${n} or $(n) if they aren't followed by whitespace.
+This feature does not support pcre2 substring names.
 
 Note: since negated patterns (those preceded by \fB!\fR) return a
 result when the expression does not match, substitutions are not
index 8a6598ef4a7280e7840d92363c89cb3b5b051f5e..896de90971f505e7654d9d3805185dd7d0afda99 100644 (file)
@@ -30,39 +30,56 @@ expression implementation that you find on many systems. </p>
 is given in the pcre_table(5) manual page. Information about PCRE
 itself can be found at http://www.pcre.org/. </p>
 
-<h2>Building Postfix with PCRE support</h2>
+<h2>Using Postfix packages with PCRE support</h2>
 
-<p> These instructions assume that you build Postfix from source
-code as described in the INSTALL document. Some modification may
-be required if you build Postfix from a vendor-specific source
-package.  </p>
-
-<p> Note: to use pcre with Debian GNU/Linux's Postfix, all you
+<p> To use pcre with Debian GNU/Linux's Postfix, or with Fedora or
+RHEL Postfix, all you
 need is to install the postfix-pcre package and you're done.  There
 is no need to recompile Postfix. </p>
 
-<p> In some future, Postfix will have a plug-in interface for adding
-map types. Until then, you need to compile PCRE support into Postfix.
-</p>
+<h2>Building Postfix from source with PCRE support</h2>
 
-<p> First of all, you need the PCRE library (Perl Compatible Regular
-Expressions), which can be obtained from: </p>
+<p> These instructions assume that you build Postfix from source
+code as described in the INSTALL document. </p>
 
-<blockquote> 
-ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/.
+<p> To build Postfix from source with pcre support, you need a pcre
+library. Install a vendor package, or download the source code from
+locations in https://www.pcre.org/ and build that yourself.
+
+<p> Postfix can build with the pcre2 library or the legacy pcre
+library. It's probably easiest to let the Postfix build procedure
+pick one. The following commands will first discover if the pcre2
+library is installed, and if that is not available, will discover
+if the legacy pcre library is installed. </p>
+
+<blockquote>
+<pre>
+$ make -f Makefile.init makefiles 
+$ make
+</pre>
 </blockquote>
 
-<p> NOTE: pcre versions prior to 2.06 cannot be used. </p>
+<p> To build Postfix explicitly with a pcre2 library (Postfix 3.7
+and later): </p>
+
+<blockquote>
+<pre>
+$ make -f Makefile.init makefiles \
+    "CCARGS=-DHAS_PCRE=2 `pcre2-config --cflags`" \
+    "AUXLIBS_PCRE=`pcre2-config --libs`"
+$ make
+</pre>
+</blockquote>
 
-<p> In order to build Postfix with PCRE support you need to add
--DHAS_PCRE and a -I option for the PCRE include file to CCARGS, and
-add the path to the PCRE library to AUXLIBS_PCRE, for example: </p>
+<p> To build Postfix explicitly with a legacy pcre library (all
+Postfix versions): </p>
 
 <blockquote>
 <pre>
-make -f Makefile.init makefiles \
-    "CCARGS=-DHAS_PCRE `pcre-config --cflags`" \
+make -f Makefile.init makefiles \
+    "CCARGS=-DHAS_PCRE=1 `pcre-config --cflags`" \
     "AUXLIBS_PCRE=`pcre-config --libs`"
+$ make
 </pre>
 </blockquote>
 
index 506f37453d2551e352c64b282a4b1c22406a0e09..cd2bd921f7aa56d9185f761d4cb505e71820b789 100644 (file)
 #      -\fR <\fIfile\fR" for header_checks(5) patterns, and
 #      "\fBpostmap -bmq -\fR <\fIfile\fR" for body_checks(5)
 #      (Postfix 2.6 and later).
+#
+#      This driver can be built with the pcre2 library (Postfix
+#      3.7 and later), or with the legacy pcre library (all Postfix
+#      versions).
 # COMPATIBILITY
 # .ad
 # .fi
@@ -73,7 +77,7 @@
 #      starts with whitespace continues a logical line.
 # .PP
 #      Each pattern is a perl-like regular expression. The expression
-#      delimiter can be any non-alphanumerical character, except
+#      delimiter can be any non-alphanumeric character, except
 #      whitespace or characters
 #      that have special meaning (traditionally the forward slash is used).
 #      The regular expression can contain whitespace.
 #      Toggles the case sensitivity flag. By default, matching is case
 #      insensitive.
 # .IP "\fBm\fR (default: off)"
-#      Toggles the PCRE_MULTILINE flag. When this flag is on, the \fB^\fR
+#      Toggles the pcre MULTILINE flag. When this flag is on, the \fB^\fR
 #      and \fB$\fR metacharacters match immediately after and immediately
 #      before a newline character, respectively, in addition to
 #      matching at the start and end of the subject string.
 # .IP "\fBs\fR (default: on)"
-#      Toggles the PCRE_DOTALL flag. When this flag is on, the \fB.\fR
+#      Toggles the pcre DOTALL flag. When this flag is on, the \fB.\fR
 #      metacharacter matches the newline character. With
 #      Postfix versions prior to 2.0, the flag is off by
 #      default, which is inconvenient for multi-line message header
 # .sp
 #      Note: do not use \fB#\fIcomment\fR after patterns.
 # .IP "\fBA\fR (default: off)"
-#      Toggles the PCRE_ANCHORED flag.  When this flag is on,
+#      Toggles the pcre ANCHORED flag.  When this flag is on,
 #      the pattern is forced to be "anchored", that is, it is
 #      constrained to match only at the start of the string which
 #      is being searched (the "subject string"). This effect can
 #      also be achieved by appropriate constructs in the pattern
 #      itself.
 # .IP "\fBE\fR (default: off)"
-#      Toggles the PCRE_DOLLAR_ENDONLY flag. When this flag is on,
+#      Toggles the pcre DOLLAR_ENDONLY flag. When this flag is on,
 #      a \fB$\fR metacharacter in the pattern matches only at the
 #      end of the subject string. Without this flag, a dollar also
 #      matches immediately before the final character if it is a
 #      newline character (but not before any other newline
-#      characters). This flag is ignored if PCRE_MULTILINE
+#      characters). This flag is ignored if the pcre MULTILINE
 #      flag is set.
 # .IP "\fBU\fR (default: off)"
-#      Toggles the ungreedy matching flag.  When this flag is on,
+#      Toggles the pcre UNGREEDY flag.  When this flag is on,
 #      the pattern matching engine inverts the "greediness" of
 #      the quantifiers so that they are not greedy by default,
 #      but become greedy if followed by "?".  This flag can also
 #      set by a (?U) modifier within the pattern.
 # .IP "\fBX\fR (default: off)"
-#      Toggles the PCRE_EXTRA flag.
+#      Toggles the pcre EXTRA flag.
 #      When this flag is on, any backslash in a pattern that is
 #      followed by a letter that has no special meaning causes an
 #      error, thus reserving these combinations for future expansion.
+#
+#      This feature is not supported with PCRE2.
 # SEARCH ORDER
 # .ad
 # .fi
 #      a $ character as output.
 #      The macros in the result string may need to be written as
 #      ${n} or $(n) if they aren't followed by whitespace.
+#      This feature does not support pcre2 substring names.
 #
 #      Note: since negated patterns (those preceded by \fB!\fR) return a
 #      result when the expression does not match, substitutions are not
index 0ca8b7734c19c352f5b2aa66d05d4e3cc4f81832..ea5fd7d4619cd8dda495d679a0bf0ef1e5895df8 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      "20211113"
+#define MAIL_RELEASE_DATE      "20211127"
 #define MAIL_VERSION_NUMBER    "3.7"
 
 #ifdef SNAPSHOT
index 9411f9e2688cabee24798ad50b983329cd972cb1..36f27404a7157ee1dd7ddbf6a83c1e2487c12070 100644 (file)
@@ -193,11 +193,12 @@ static void postcat(VSTREAM *fp, VSTRING *buffer, int flags)
            for (offset = 0; offset < start_offset; offset++)
                if (VSTREAM_GETC(fp) == VSTREAM_EOF)
                    msg_fatal("%s: skip %ld bytes failed after %ld",
-                             VSTREAM_PATH(fp), start_offset, offset);
+                             VSTREAM_PATH(fp), (long) start_offset,
+                             (long) offset);
        } else {
            if (vstream_fseek(fp, start_offset, SEEK_SET) < 0)
                msg_fatal("%s: seek to %ld: %m",
-                         VSTREAM_PATH(fp), start_offset);
+                         VSTREAM_PATH(fp), (long) start_offset);
        }
     }
 
index 47e4674421c6fc58f02025ee86f19a93edc94258..5b211b58a08797af30287f73237b205c00cef6d8 100644 (file)
@@ -568,19 +568,22 @@ dict_stream: $(LIB)
 
 tests: all valid_hostname_test mac_expand_test dict_test unescape_test \
        hex_quote_test ctable_test inet_addr_list_test base64_code_test \
-       attr_scan64_test attr_scan0_test dict_pcre_test host_port_test \
+       attr_scan64_test attr_scan0_test dict_pcre_tests host_port_test \
        dict_cidr_test attr_scan_plain_test htable_test hex_code_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_regexp_test \
        dict_union_test dict_pipe_test miss_endif_cidr_test \
-       miss_endif_pcre_test miss_endif_regexp_test split_qnameval_test \
-       vstring_test vstream_test dict_pcre_file_test dict_regexp_file_test \
-       dict_cidr_file_test dict_static_file_test dict_random_test \
-       dict_random_file_test dict_inline_file_test byte_mask_tests \
-       mystrtok_test known_tcp_ports_test dict_stream_test \
-       dict_inline_pcre_test dict_inline_regexp_test dict_inline_cidr_test
+       miss_endif_regexp_test split_qnameval_test vstring_test \
+       vstream_test dict_regexp_file_test dict_cidr_file_test \
+       dict_static_file_test dict_random_test dict_random_file_test \
+       dict_inline_file_test byte_mask_tests mystrtok_test \
+       known_tcp_ports_test dict_stream_test dict_inline_regexp_test \
+       dict_inline_cidr_test
+
+dict_pcre_tests: dict_pcre_test miss_endif_pcre_test dict_pcre_file_test \
+       dict_inline_pcre_test
 
 root_tests:
 
@@ -648,7 +651,9 @@ dict_test: dict_open testdb dict_test.in dict_test.ref
        rm -f testdb.db testdb.dir testdb.pag dict_test.tmp
 
 dict_pcre_test: dict_open dict_pcre.in dict_pcre.map dict_pcre.ref
-       $(SHLIB_ENV) ${VALGRIND} ./dict_open pcre:dict_pcre.map read <dict_pcre.in 2>&1 | sed 's/uid=[0-9][0-9][0-9]*/uid=USER/' >dict_pcre.tmp
+       $(SHLIB_ENV) ${VALGRIND} ./dict_open pcre:dict_pcre.map read \
+           <dict_pcre.in 2>&1 | sed -e 's/uid=[0-9][0-9][0-9]*/uid=USER/' \
+           -e 's/missing )/missing closing parenthesis/' >dict_pcre.tmp
        diff dict_pcre.ref dict_pcre.tmp
        rm -f dict_pcre.tmp
 
index f4ddb2ede3cbeabe54b4a459ad396a80c2616f97..3cceda2c3a4088bc962695442bb5468a3829075d 100644 (file)
 #include <strings.h>
 #endif
 
+#if HAS_PCRE == 1
+#include <pcre.h>
+#elif HAS_PCRE == 2
+#define PCRE2_CODE_UNIT_WIDTH  8
+#include <pcre2.h>
+#else
+#error "define HAS_PCRE=2 or HAS_PCRE=1"
+#endif
+
 /* Utility library. */
 
 #include "mymalloc.h"
 #include "dict.h"
 #include "dict_pcre.h"
 #include "mac_parse.h"
-#include "pcre.h"
 #include "warn_stat.h"
 #include "mvect.h"
 
  /*
   * Backwards compatibility.
   */
+#if HAS_PCRE == 1
+ /* PCRE Legacy JIT supprt. */
 #ifdef PCRE_STUDY_JIT_COMPILE
 #define DICT_PCRE_FREE_STUDY(x)        pcre_free_study(x)
 #else
 #define DICT_PCRE_FREE_STUDY(x)        pcre_free((char *) (x))
 #endif
 
+ /* PCRE Compiled pattern. */
+#define DICT_PCRE_CODE         pcre
+#define DICT_PCRE_CODE_FREE(x) myfree((void *) (x))
+
+ /* Old-style hints versus new-style match_data. */
+#define DICT_PCRE_MATCH_HINT_TYPE pcre_extra *
+#define DICT_PCRE_MATCH_HINT_NAME hints
+#define DICT_PCRE_MATCH_HINT(x) ((x)->DICT_PCRE_MATCH_HINT_NAME)
+#define DICT_PCRE_MATCH_HINT_FREE(x) do { \
+       if (DICT_PCRE_MATCH_HINT(x)) \
+           DICT_PCRE_FREE_STUDY(DICT_PCRE_MATCH_HINT(x)); \
+    } while (0)
+
+ /* PCRE Pattern options. */
+#define DICT_PCRE_CASELESS     PCRE_CASELESS
+#define DICT_PCRE_MULTILINE    PCRE_MULTILINE
+#define DICT_PCRE_DOTALL       PCRE_DOTALL
+#define DICT_PCRE_EXTENDED     PCRE_EXTENDED
+#define DICT_PCRE_ANCHORED     PCRE_ANCHORED
+#define DICT_PCRE_DOLLAR_ENDONLY PCRE_DOLLAR_ENDONLY
+#define DICT_PCRE_UNGREEDY     PCRE_UNGREEDY
+#define DICT_PCRE_EXTRA                PCRE_EXTRA
+
+ /* PCRE Number of captures in pattern. */
+#ifdef PCRE_INFO_CAPTURECOUNT
+#define DICT_PCRE_CAPTURECOUNT_T int
+#endif
+
+#else                                  /* HAS_PCRE */
+
+ /* PCRE2 Compiled pattern. */
+#define DICT_PCRE_CODE         pcre2_code
+#define DICT_PCRE_CODE_FREE(x) pcre2_code_free(x)
+
+ /* PCRE2 Old-style hints versus new-style match_data. */
+#define DICT_PCRE_MATCH_HINT_TYPE pcre2_match_data *
+#define DICT_PCRE_MATCH_HINT_NAME match_data
+#define DICT_PCRE_MATCH_HINT(x)        ((x)->DICT_PCRE_MATCH_HINT_NAME)
+#define DICT_PCRE_MATCH_HINT_FREE(x) \
+       pcre2_match_data_free(DICT_PCRE_MATCH_HINT(x))
+
+ /* PCRE2 Pattern options. */
+#define DICT_PCRE_CASELESS     PCRE2_CASELESS
+#define DICT_PCRE_MULTILINE    PCRE2_MULTILINE
+#define DICT_PCRE_DOTALL       PCRE2_DOTALL
+#define DICT_PCRE_EXTENDED     PCRE2_EXTENDED
+#define DICT_PCRE_ANCHORED     PCRE2_ANCHORED
+#define DICT_PCRE_DOLLAR_ENDONLY PCRE2_DOLLAR_ENDONLY
+#define DICT_PCRE_UNGREEDY     PCRE2_UNGREEDY
+#define DICT_PCRE_EXTRA                0
+
+ /* PCRE2 Number of captures in pattern. */
+#define        DICT_PCRE_CAPTURECOUNT_T uint32_t
+
+#endif                                 /* HAS_PCRE */
+
  /*
   * Support for IF/ENDIF based on an idea by Bert Driehuis.
   */
  /*
   * Max strings captured by regexp - essentially the max number of (..)
   */
+#if HAS_PCRE == 1
 #define PCRE_MAX_CAPTURE       99
+#endif
 
  /*
   * Regular expression before and after compilation.
@@ -98,8 +166,8 @@ typedef struct {
 } DICT_PCRE_REGEXP;
 
 typedef struct {
-    pcre   *pattern;                   /* the compiled pattern */
-    pcre_extra *hints;                 /* hints to speed pattern execution */
+    DICT_PCRE_CODE *pattern;           /* the compiled pattern */
+    DICT_PCRE_MATCH_HINT_TYPE DICT_PCRE_MATCH_HINT_NAME;
 } DICT_PCRE_ENGINE;
 
  /*
@@ -113,8 +181,8 @@ typedef struct DICT_PCRE_RULE {
 
 typedef struct {
     DICT_PCRE_RULE rule;               /* generic part */
-    pcre   *pattern;                   /* compiled pattern */
-    pcre_extra *hints;                 /* hints to speed pattern execution */
+    DICT_PCRE_CODE *pattern;           /* compiled pattern */
+    DICT_PCRE_MATCH_HINT_TYPE DICT_PCRE_MATCH_HINT_NAME;
     char   *replacement;               /* replacement string */
     int     match;                     /* positive or negative match */
     size_t  max_sub;                   /* largest $number in replacement */
@@ -122,8 +190,8 @@ typedef struct {
 
 typedef struct {
     DICT_PCRE_RULE rule;               /* generic members */
-    pcre   *pattern;                   /* compiled pattern */
-    pcre_extra *hints;                 /* hints to speed pattern execution */
+    DICT_PCRE_CODE *pattern;           /* compiled pattern */
+    DICT_PCRE_MATCH_HINT_TYPE DICT_PCRE_MATCH_HINT_NAME;
     int     match;                     /* positive or negative match */
     struct DICT_PCRE_RULE *endif_rule; /* matching endif rule */
 } DICT_PCRE_IF_RULE;
@@ -137,16 +205,25 @@ typedef struct {
     VSTRING *expansion_buf;            /* lookup result */
 } DICT_PCRE;
 
+#if HAS_PCRE == 1
 static int dict_pcre_init = 0;         /* flag need to init pcre library */
 
+#endif
+
 /*
  * Context for $number expansion callback.
  */
 typedef struct {
     DICT_PCRE *dict_pcre;              /* the dictionary handle */
+#if HAS_PCRE == 1
     DICT_PCRE_MATCH_RULE *match_rule;  /* the rule we matched */
+#endif
     const char *lookup_string;         /* string against which we match */
+#if HAS_PCRE == 1
     int     offsets[PCRE_MAX_CAPTURE * 3];     /* Cut substrings */
+#else                                  /* HAS_PCRE */
+    PCRE2_SIZE *ovector;               /* matched string offsets */
+#endif                                 /* HAS_PCRE */
     int     matches;                   /* Count of cuts */
 } DICT_PCRE_EXPAND_CONTEXT;
 
@@ -172,25 +249,32 @@ typedef struct {
   */
 #define NULL_STARTOFFSET       (0)
 #define NULL_EXEC_OPTIONS      (0)
-#define NULL_OVECTOR           ((int *) 0)
-#define NULL_OVECTOR_LENGTH    (0)
 
 /* dict_pcre_expand - replace $number with matched text */
 
 static int dict_pcre_expand(int type, VSTRING *buf, void *ptr)
 {
     DICT_PCRE_EXPAND_CONTEXT *ctxt = (DICT_PCRE_EXPAND_CONTEXT *) ptr;
-    DICT_PCRE_MATCH_RULE *match_rule = ctxt->match_rule;
     DICT_PCRE *dict_pcre = ctxt->dict_pcre;
-    const char *pp;
     int     n;
+
+#if HAS_PCRE == 1
+    DICT_PCRE_MATCH_RULE *match_rule = ctxt->match_rule;
+    const char *pp;
     int     ret;
 
+#else
+    PCRE2_SPTR start;
+    PCRE2_SIZE length;
+
+#endif
+
     /*
      * Replace $0-${99} with strings cut from matched text.
      */
     if (type == MAC_PARSE_VARNAME) {
        n = atoi(vstring_str(buf));
+#if HAS_PCRE == 1
        ret = pcre_get_substring(ctxt->lookup_string, ctxt->offsets,
                                 ctxt->matches, n, &pp);
        if (ret < 0) {
@@ -207,6 +291,14 @@ static int dict_pcre_expand(int type, VSTRING *buf, void *ptr)
        vstring_strcat(dict_pcre->expansion_buf, pp);
        myfree((void *) pp);
        return (MAC_PARSE_OK);
+#else
+       start = (unsigned char *) ctxt->lookup_string + ctxt->ovector[2 * n];
+       length = ctxt->ovector[2 * n + 1] - ctxt->ovector[2 * n];
+       if (length == 0)
+           return (MAC_PARSE_UNDEF);
+       vstring_strncat(dict_pcre->expansion_buf, (char *) start, length);
+       return (MAC_PARSE_OK);
+#endif
     }
 
     /*
@@ -218,10 +310,33 @@ static int dict_pcre_expand(int type, VSTRING *buf, void *ptr)
     }
 }
 
+#if HAS_PCRE == 2
+
+#define DICT_PCRE_GET_ERROR_BUF_LEN    256
+
+/* dict_pcre_get_error - convert PCRE2 error number or text */
+
+static char *dict_pcre_get_error(VSTRING *buf, int errval)
+{
+    ssize_t len;
+
+    VSTRING_SPACE(buf, DICT_PCRE_GET_ERROR_BUF_LEN);
+    if ((len = pcre2_get_error_message(errval,
+                                      (unsigned char *) vstring_str(buf),
+                                      DICT_PCRE_GET_ERROR_BUF_LEN)) > 0) {
+       vstring_set_payload_size(buf, len);
+    } else
+       vstring_sprintf(buf, "unexpected pcre2 error code %d", errval);
+    return (vstring_str(buf));
+}
+
+#endif                                 /* HAS_PCRE == 2 */
+
 /* dict_pcre_exec_error - report matching error */
 
 static void dict_pcre_exec_error(const char *mapname, int lineno, int errval)
 {
+#if HAS_PCRE == 1
     switch (errval) {
        case 0:
        msg_warn("pcre map %s, line %d: too many (...)",
@@ -266,11 +381,19 @@ static void dict_pcre_exec_error(const char *mapname, int lineno, int errval)
                 mapname, lineno, errval);
        return;
     }
+#else                                  /* HAS_PCRE */
+    VSTRING *buf = vstring_alloc(DICT_PCRE_GET_ERROR_BUF_LEN);
+
+    msg_warn("pcre map %s, line %d: %s", mapname, lineno,
+            dict_pcre_get_error(buf, errval));
+    vstring_free(buf);
+#endif                                         /* HAS_PCRE */
 }
 
  /*
   * Inlined to reduce function call overhead in the time-critical loop.
   */
+#if HAS_PCRE == 1
 #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, \
@@ -278,6 +401,15 @@ static void dict_pcre_exec_error(const char *mapname, int lineno, int errval)
      (ctxt).matches > 0 ? (match) : \
      (ctxt).matches == PCRE_ERROR_NOMATCH ? !(match) : \
      (dict_pcre_exec_error((map), (line), (ctxt).matches), 0))
+#else
+#define DICT_PCRE_EXEC(ctxt, map, line, pattern, match_data, match, str, len) \
+    ((ctxt).matches = pcre2_match((pattern), (unsigned char *) (str), (len), \
+                               NULL_STARTOFFSET, NULL_EXEC_OPTIONS, \
+                               (match_data), (pcre2_match_context *) 0), \
+     (ctxt).matches > 0 ? (match) : \
+     (ctxt).matches == PCRE2_ERROR_NOMATCH ? !(match) : \
+     (dict_pcre_exec_error((map), (line), (ctxt).matches), 0))
+#endif
 
 /* dict_pcre_lookup - match string and perform optional substitution */
 
@@ -314,7 +446,8 @@ static const char *dict_pcre_lookup(DICT *dict, const char *lookup_string)
        case DICT_PCRE_OP_MATCH:
            match_rule = (DICT_PCRE_MATCH_RULE *) rule;
            if (!DICT_PCRE_EXEC(ctxt, dict->name, rule->lineno,
-                               match_rule->pattern, match_rule->hints,
+                               match_rule->pattern,
+                               DICT_PCRE_MATCH_HINT(match_rule),
                              match_rule->match, lookup_string, lookup_len))
                continue;
 
@@ -333,7 +466,11 @@ static const char *dict_pcre_lookup(DICT *dict, const char *lookup_string)
                dict_pcre->expansion_buf = vstring_alloc(10);
            VSTRING_RESET(dict_pcre->expansion_buf);
            ctxt.dict_pcre = dict_pcre;
+#if HAS_PCRE == 1
            ctxt.match_rule = match_rule;
+#else
+           ctxt.ovector = pcre2_get_ovector_pointer(match_rule->match_data);
+#endif
            ctxt.lookup_string = lookup_string;
 
            if (mac_parse(match_rule->replacement, dict_pcre_expand,
@@ -353,7 +490,8 @@ static const char *dict_pcre_lookup(DICT *dict, const char *lookup_string)
        case DICT_PCRE_OP_IF:
            if_rule = (DICT_PCRE_IF_RULE *) rule;
            if (DICT_PCRE_EXEC(ctxt, dict->name, rule->lineno,
-                              if_rule->pattern, if_rule->hints,
+                              if_rule->pattern,
+                              DICT_PCRE_MATCH_HINT(if_rule),
                               if_rule->match, lookup_string, lookup_len))
                continue;
            /* An IF without matching ENDIF has no "endif" rule. */
@@ -390,18 +528,16 @@ static void dict_pcre_close(DICT *dict)
        case DICT_PCRE_OP_MATCH:
            match_rule = (DICT_PCRE_MATCH_RULE *) rule;
            if (match_rule->pattern)
-               myfree((void *) match_rule->pattern);
-           if (match_rule->hints)
-               DICT_PCRE_FREE_STUDY(match_rule->hints);
+               DICT_PCRE_CODE_FREE(match_rule->pattern);
+           DICT_PCRE_MATCH_HINT_FREE(match_rule);
            if (match_rule->replacement)
                myfree((void *) match_rule->replacement);
            break;
        case DICT_PCRE_OP_IF:
            if_rule = (DICT_PCRE_IF_RULE *) rule;
            if (if_rule->pattern)
-               myfree((void *) if_rule->pattern);
-           if (if_rule->hints)
-               DICT_PCRE_FREE_STUDY(if_rule->hints);
+               DICT_PCRE_CODE_FREE(if_rule->pattern);
+           DICT_PCRE_MATCH_HINT_FREE(if_rule);
            break;
        case DICT_PCRE_OP_ENDIF:
            break;
@@ -467,32 +603,37 @@ static int dict_pcre_get_pattern(const char *mapname, int lineno, char **bufp,
     /*
      * Parse any regexp options.
      */
-    pattern->options = PCRE_CASELESS | PCRE_DOTALL;
+    pattern->options = DICT_PCRE_CASELESS | DICT_PCRE_DOTALL;
     while (*p && !ISSPACE(*p)) {
        switch (*p) {
        case 'i':
-           pattern->options ^= PCRE_CASELESS;
+           pattern->options ^= DICT_PCRE_CASELESS;
            break;
        case 'm':
-           pattern->options ^= PCRE_MULTILINE;
+           pattern->options ^= DICT_PCRE_MULTILINE;
            break;
        case 's':
-           pattern->options ^= PCRE_DOTALL;
+           pattern->options ^= DICT_PCRE_DOTALL;
            break;
        case 'x':
-           pattern->options ^= PCRE_EXTENDED;
+           pattern->options ^= DICT_PCRE_EXTENDED;
            break;
        case 'A':
-           pattern->options ^= PCRE_ANCHORED;
+           pattern->options ^= DICT_PCRE_ANCHORED;
            break;
        case 'E':
-           pattern->options ^= PCRE_DOLLAR_ENDONLY;
+           pattern->options ^= DICT_PCRE_DOLLAR_ENDONLY;
            break;
        case 'U':
-           pattern->options ^= PCRE_UNGREEDY;
+           pattern->options ^= DICT_PCRE_UNGREEDY;
            break;
        case 'X':
-           pattern->options ^= PCRE_EXTRA;
+#if DICT_PCRE_EXTRA != 0
+           pattern->options ^= DICT_PCRE_EXTRA;
+#else
+           msg_warn("pcre map %s, line %d: ignoring obsolete regexp "
+                    "option \"%c\"", mapname, lineno, *p);
+#endif
            break;
        default:
            msg_warn("pcre map %s, line %d: unknown regexp option \"%c\": "
@@ -550,6 +691,7 @@ static int dict_pcre_compile(const char *mapname, int lineno,
                                     DICT_PCRE_REGEXP *pattern,
                                     DICT_PCRE_ENGINE *engine)
 {
+#if HAS_PCRE == 1
     const char *error;
     int     errptr;
 
@@ -564,9 +706,28 @@ static int dict_pcre_compile(const char *mapname, int lineno,
     if (error != 0) {
        msg_warn("pcre map %s, line %d: error while studying regex: %s",
                 mapname, lineno, error);
-       myfree((void *) engine->pattern);
+       DICT_PCRE_CODE_FREE(engine->pattern);
+       return (0);
+    }
+#else
+    int     error;
+    size_t  errptr;
+
+    engine->pattern = pcre2_compile((unsigned char *) pattern->regexp,
+                                   PCRE2_ZERO_TERMINATED,
+                                   pattern->options, &error, &errptr, NULL);
+    if (engine->pattern == 0) {
+       VSTRING *buf = vstring_alloc(DICT_PCRE_GET_ERROR_BUF_LEN);
+
+       msg_warn("pcre map %s, line %d: error in regex at offset %lu: %s",
+                mapname, lineno, (unsigned long) errptr,
+                dict_pcre_get_error(buf, error));
+       vstring_free(buf);
        return (0);
     }
+    engine->match_data = pcre2_match_data_create_from_pattern(
+                                              engine->pattern, (void *) 0);
+#endif
     return (1);
 }
 
@@ -591,7 +752,15 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(DICT *dict, const char *mapname,
                                                    int nesting)
 {
     char   *p;
-    int     actual_sub;
+
+#ifdef DICT_PCRE_CAPTURECOUNT_T
+    DICT_PCRE_CAPTURECOUNT_T actual_sub;
+
+#endif
+#if 0
+    uint32_t namecount;
+
+#endif
 
     p = line;
 
@@ -676,23 +845,43 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(DICT *dict, const char *mapname,
         */
        if (dict_pcre_compile(mapname, lineno, &regexp, &engine) == 0)
            CREATE_MATCHOP_ERROR_RETURN(0);
-#ifdef PCRE_INFO_CAPTURECOUNT
+#ifdef DICT_PCRE_CAPTURECOUNT_T
+#if HAS_PCRE == 1
        if (pcre_fullinfo(engine.pattern, engine.hints,
                          PCRE_INFO_CAPTURECOUNT,
                          (void *) &actual_sub) != 0)
            msg_panic("pcre map %s, line %d: pcre_fullinfo failed",
                      mapname, lineno);
+#else                                          /* HAS_PCRE */
+#if 0
+       if (pcre2_pattern_info(
+                    engine.pattern, PCRE2_INFO_NAMECOUNT, &namecount) != 0)
+           msg_panic("pcre map %s, line %d: pcre2_pattern_info failed",
+                     mapname, lineno);
+       if (namecount > 0) {
+           msg_warn("pcre map %s, line %d: named substrings are not supported",
+                    mapname, lineno);
+           if (engine.pattern)
+               DICT_PCRE_CODE_FREE(engine.pattern);
+           DICT_PCRE_MATCH_HINT_FREE(&engine);
+           CREATE_MATCHOP_ERROR_RETURN(0);
+       }
+#endif
+       if (pcre2_pattern_info(engine.pattern, PCRE2_INFO_CAPTURECOUNT,
+                              (void *) &actual_sub) != 0)
+           msg_panic("pcre map %s, line %d: pcre2_pattern_info failed",
+                     mapname, lineno);
+#endif                                         /* HAS_PCRE */
        if (prescan_context.max_sub > actual_sub) {
            msg_warn("pcre map %s, line %d: out of range replacement index \"%d\": "
                     "skipping this rule", mapname, lineno,
                     (int) prescan_context.max_sub);
            if (engine.pattern)
-               myfree((void *) engine.pattern);
-           if (engine.hints)
-               DICT_PCRE_FREE_STUDY(engine.hints);
+               DICT_PCRE_CODE_FREE(engine.pattern);
+           DICT_PCRE_MATCH_HINT_FREE(&engine);
            CREATE_MATCHOP_ERROR_RETURN(0);
        }
-#endif
+#endif                                         /* DICT_PCRE_CAPTURECOUNT_T */
 
        /*
         * Save the result.
@@ -707,7 +896,7 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(DICT *dict, const char *mapname,
        else
            match_rule->replacement = mystrdup(p);
        match_rule->pattern = engine.pattern;
-       match_rule->hints = engine.hints;
+       DICT_PCRE_MATCH_HINT(match_rule) = DICT_PCRE_MATCH_HINT(&engine);
        return ((DICT_PCRE_RULE *) match_rule);
     }
 
@@ -755,7 +944,7 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(DICT *dict, const char *mapname,
                                 sizeof(DICT_PCRE_IF_RULE));
        if_rule->match = regexp.match;
        if_rule->pattern = engine.pattern;
-       if_rule->hints = engine.hints;
+       DICT_PCRE_MATCH_HINT(if_rule) = DICT_PCRE_MATCH_HINT(&engine);
        if_rule->endif_rule = 0;
        return ((DICT_PCRE_RULE *) if_rule);
     }
@@ -866,11 +1055,13 @@ DICT   *dict_pcre_open(const char *mapname, int open_flags, int dict_flags)
     dict_pcre->head = 0;
     dict_pcre->expansion_buf = 0;
 
+#if HAS_PCRE == 1
     if (dict_pcre_init == 0) {
        pcre_malloc = (void *(*) (size_t)) mymalloc;
        pcre_free = (void (*) (void *)) myfree;
        dict_pcre_init = 1;
     }
+#endif
     dict_pcre->dict.owner.uid = st.st_uid;
     dict_pcre->dict.owner.status = (st.st_uid != 0);
 
index 7a6cefb6f84e9aa5ef7f6b4a406c078eb6502aba..23c976a0ad3207f0348524a8b57d16742d30d38c 100644 (file)
@@ -25,3 +25,4 @@ endif
 endif
 if /./
 if /./
+/(/            unused
index 23eef8e01fd6c2c10a0ede4fd245006df1adf4f3..9b14678b5b66be320081c64c6cf1708a3aada684 100644 (file)
@@ -8,6 +8,7 @@
 ./dict_open: warning: pcre map dict_pcre.map, line 22: no regexp: skipping this rule
 ./dict_open: warning: pcre map dict_pcre.map, line 24: ignoring ENDIF without matching IF
 ./dict_open: warning: pcre map dict_pcre.map, line 25: ignoring ENDIF without matching IF
+./dict_open: warning: pcre map dict_pcre.map, line 28: error in regex at offset 1: missing closing parenthesis
 ./dict_open: warning: pcre map dict_pcre.map, line 27: IF has no matching ENDIF
 ./dict_open: warning: pcre map dict_pcre.map, line 26: IF has no matching ENDIF
 owner=untrusted (uid=USER)