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.
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-
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
====================================
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.
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>
<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.
terns, and "<b>postmap -bmq -</b> <<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.
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.
<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>.
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
# 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
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
# 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_/)
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
\-\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
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.
.SH "SEARCH ORDER"
.na
.nf
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
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>
# -\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
# 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
* 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
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);
}
}
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:
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
#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.
} 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;
/*
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 */
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;
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;
*/
#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) {
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
}
/*
}
}
+#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 (...)",
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, \
(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 */
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;
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,
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. */
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;
/*
* 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\": "
DICT_PCRE_REGEXP *pattern,
DICT_PCRE_ENGINE *engine)
{
+#if HAS_PCRE == 1
const char *error;
int errptr;
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);
}
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;
*/
if (dict_pcre_compile(mapname, lineno, ®exp, &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.
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);
}
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);
}
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);
endif
if /./
if /./
+/(/ unused
./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)