Commit 72a038bf authored by Geoff Simmons's avatar Geoff Simmons

initial commit, passes tests for an initial version of regex.match()

and the config_*() functions
parents
((nil . ((indent-tabs-mode . t)))
(c-mode . ((c-file-style . "BSD"))))
Makefile
Makefile.in
.deps/
.libs/
*.o
*.lo
*.la
*~
*.[1-9]
/aclocal.m4
/autom4te.cache/
/compile
/config.guess
/config.h
/config.h.in
/config.log
/config.status
/config.sub
/configure
/depcomp
/install-sh
/libtool
/ltmain.sh
/missing
/stamp-h1
/m4/libtool.m4
/m4/lt*.m4
/src/vcc_if.c
/src/vcc_if.h
/src/vmod_*rst
CONTRIBUTING
============
To contribute code or documentation, submit a pull request at the
`source repository website
<https://code.uplex.de/uplex-varnish/libvmod-pcre2>`_.
If you have a problem or discover a bug, you can post an `issue
<https://code.uplex.de/uplex-varnish/libvmod-pcre2/issues>`_ at
the website. You can also write to <varnish-support@uplex.de>.
For developers
--------------
The build specifies C99 conformance, all compiler warnings turned on,
and all warnings considered errors (compiler options ``-std=c99
-Werror -Wall -Wextra``).
The VMOD has been tested with both the gcc and clang compilers, and
should always compile and test successfully with both of them.
By default, ``CFLAGS`` is set to ``-g -O2``, so that symbols are
included in the shared library, and optimization is at level
``O2``. To change or disable these options, set ``CFLAGS`` explicitly
before calling ``make`` (it may be set to the empty string).
For development/debugging cycles, the ``configure`` option
``--enable-debugging`` is recommended (off by default). This will turn
off optimizations and function inlining, so that a debugger will step
through the code as expected.
See LICENSE for details.
INSTALLATION
============
The VMOD is built against a Varnish installation, and the autotools
use ``pkg-config(1)`` to locate the necessary header files and other
resources. This sequence will install the VMOD::
> ./autogen.sh # for builds from the git repo
> ./configure
> make
> make check # to run unit tests in src/tests/*.vtc
> sudo make install
If you have installed Varnish in a non-standard directory, call
``autogen.sh`` and ``configure`` with the ``PKG_CONFIG_PATH``
environment variable pointing to the appropriate path. For example,
when varnishd configure was called with ``--prefix=$PREFIX``, use::
> PKG_CONFIG_PATH=${PREFIX}/lib/pkgconfig
> export PKG_CONFIG_PATH
By default, the vmod ``configure`` script installs the vmod in
the same directory as Varnish, determined via ``pkg-config(1)``. The
vmod installation directory can be overridden by passing the
``VMOD_DIR`` variable to ``configure``.
Other files such as the man-page are installed in the locations
determined by ``configure``, which inherits its default ``--prefix``
setting from Varnish.
Copyright (c) 2017 UPLEX Nils Goroll Systemoptimierung
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
ACLOCAL_AMFLAGS = -I m4 -I ${LIBVARNISHAPI_DATAROOTDIR}/aclocal
SUBDIRS = src
DISTCHECK_CONFIGURE_FLAGS = \
VMOD_DIR='$${libdir}/varnish/vmods'
EXTRA_DIST = README.rst LICENSE COPYING
doc_DATA = README.rst LICENSE COPYING
dist_man_MANS = vmod_pcre2.3
MAINTAINERCLEANFILES = $(dist_man_MANS)
vmod_pcre2.3: README.rst
README.rst: src/vmod_pcre2.man.rst
cp src/vmod_pcre2.man.rst README.rst
src/vmod_pcre2.man.rst:
make -C src vmod_pcre2.man.rst
%.1 %.2 %.3 %.4 %.5 %.6 %.7 %.8 %.9:
if HAVE_RST2MAN
${RST2MAN} $< $@
else
@echo "========================================"
@echo "You need rst2man installed to make dist"
@echo "========================================"
@false
endif
..
.. NB: This file is machine generated, DO NOT EDIT!
..
.. Edit vmod.vcc and run make instead
..
.. role:: ref(emphasis)
.. _vmod_pcre2(3):
==========
vmod_pcre2
==========
-------------------------------------------
access the pcre2 regular expression library
-------------------------------------------
:Manual section: 3
SYNOPSIS
========
import pcre2 [from "path"] ;
::
new OBJECT = ...
DESCRIPTION
===========
This Varnish Module (VMOD) provides access to the PCRE2 regular
expresion library.
CONTENTS
========
* regex(STRING, ENUM {LIB8,LIB16,LIB32}, BOOL, BOOL, ENUM {ANYCRLF,UNICODE}, BOOL, BOOL, BOOL, BOOL, BOOL, BOOL, BOOL, BOOL, BOOL, STRING, BOOL, INT, BOOL, BOOL, BOOL, BOOL, ENUM {CR,LF,CRLF,ANYCRLF,ANY}, BOOL, BOOL, BOOL, BOOL, BOOL, INT, BOOL, BOOL, BOOL, BOOL)
* BOOL config_bool(ENUM {JIT,STACKRECURSE,UNICODE}, ENUM {LIB8,LIB16,LIB32})
* STRING config_str(ENUM {BSR,JITTARGET,NEWLINE,UNICODE_VERSION,VERSION}, ENUM {LIB8,LIB16,LIB32})
* INT config_int(ENUM {LINKSIZE,MATCHLIMIT,PARENSLIMIT,RECURSIONLIMIT}, ENUM {LIB8,LIB16,LIB32})
* STRING version()
.. _obj_regex:
regex
-----
::
new OBJ = regex(STRING pattern, ENUM {LIB8,LIB16,LIB32} lib=0, BOOL allow_empty_class=0, BOOL anchored=0, ENUM {ANYCRLF,UNICODE} bsr=0, BOOL alt_bsux=0, BOOL alt_circumflex=0, BOOL alt_verbnames=0, BOOL caseless=0, BOOL dotall=0, BOOL dollar_endonly=0, BOOL dupnames=0, BOOL extended=0, BOOL firstline=0, STRING locale=0, BOOL match_unset_backref=0, INT max_pattern_len=0, BOOL multiline=0, BOOL never_backslash_c=0, BOOL never_ucp=0, BOOL never_utf=0, ENUM {CR,LF,CRLF,ANYCRLF,ANY} newline=0, BOOL no_auto_capture=0, BOOL no_auto_possess=0, BOOL no_dotstar_anchor=0, BOOL no_start_optimize=0, BOOL no_utf_check=0, INT parens_nest_limit=0, BOOL ucp=0, BOOL ungreedy=0, BOOL use_offset_limit=0, BOOL utf=0)
# XXX options for dfa_match, jit fast path, start_offset
.. _func_regex.match:
regex.match
-----------
::
BOOL regex.match(PRIV_TASK, STRING, INT len=0, BOOL anchored=0, INT match_limit=0, INT offset_limit=0, BOOL notbol=0, BOOL noteol=0, BOOL notempty=0, BOOL notempty_atstart=0, BOOL no_jit=0, BOOL no_utf_check=0, ENUM {HARD,SOFT} partial=0, INT recursion_limit=0)
.. _func_config_bool:
config_bool
-----------
::
BOOL config_bool(ENUM {JIT,STACKRECURSE,UNICODE}, ENUM {LIB8,LIB16,LIB32} lib=0)
.. _func_config_str:
config_str
----------
::
STRING config_str(ENUM {BSR,JITTARGET,NEWLINE,UNICODE_VERSION,VERSION}, ENUM {LIB8,LIB16,LIB32} lib=0)
.. _func_config_int:
config_int
----------
::
INT config_int(ENUM {LINKSIZE,MATCHLIMIT,PARENSLIMIT,RECURSIONLIMIT}, ENUM {LIB8,LIB16,LIB32} lib=0)
.. _func_version:
version
-------
::
STRING version()
Returns the version string for this VMOD.
Example::
std.log("Using VMOD pcre2 version " + pcre2.version());
REQUIREMENTS
============
This VMOD requires Varnish ...
LIMITATIONS
===========
...
INSTALLATION
============
See `INSTALL.rst <INSTALL.rst>`_ in the source repository.
SEE ALSO
========
* varnishd(1)
* vcl(7)
* source repository: https://code.uplex.de/uplex-varnish/libvmod-pcre2
COPYRIGHT
=========
::
This document is licensed under the same conditions
as the libvmod-pcre2 project. See LICENSE for details.
Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
#!/bin/sh
warn() {
echo "WARNING: $@" 1>&2
}
case `uname -s` in
Darwin)
LIBTOOLIZE=glibtoolize
;;
FreeBSD)
LIBTOOLIZE=libtoolize
;;
Linux)
LIBTOOLIZE=libtoolize
;;
SunOS)
LIBTOOLIZE=libtoolize
;;
*)
warn "unrecognized platform:" `uname -s`
LIBTOOLIZE=libtoolize
esac
automake_version=`automake --version | tr ' ' '\n' | egrep '^[0-9]\.[0-9a-z.-]+'`
if [ -z "$automake_version" ] ; then
warn "unable to determine automake version"
else
case $automake_version in
0.*|1.[0-8]|1.[0-8][.-]*)
warn "automake ($automake_version) detected; 1.9 or newer recommended"
;;
*)
;;
esac
fi
# check for varnishapi.m4 in custom paths
dataroot=$(pkg-config --variable=datarootdir varnishapi 2>/dev/null)
if [ -z "$dataroot" ] ; then
cat >&2 <<'EOF'
Package varnishapi was not found in the pkg-config search path.
Perhaps you should add the directory containing `varnishapi.pc'
to the PKG_CONFIG_PATH environment variable
EOF
exit 1
fi
set -ex
aclocal -I m4 -I ${dataroot}/aclocal
$LIBTOOLIZE --copy --force
autoheader
automake --add-missing --copy --foreign
autoconf
AC_PREREQ(2.59)
AC_COPYRIGHT([Copyright (c) 2017 UPLEX - Nils Goroll Systemoptimierung])
AC_INIT([VMOD pcre2], [trunk], [varnish-support@uplex.de], [libvmod-pcre2],
[https://code.uplex.de/uplex-varnish/libvmod-pcre2])
AC_CONFIG_MACRO_DIR([m4])
m4_ifndef([VARNISH_VMOD_INCLUDES],
AC_MSG_ERROR([Need varnish.m4 -- see README.rst]))
AC_CONFIG_SRCDIR(src/vmod_pcre2.vcc)
AM_CONFIG_HEADER(config.h)
AC_CANONICAL_SYSTEM
AC_LANG(C)
AM_INIT_AUTOMAKE([foreign])
AC_GNU_SOURCE
AC_PROG_CC
AC_PROG_CC_C99
if test "x$ac_cv_prog_cc_c99" = xno; then
AC_MSG_ERROR([Could not find a C99 compatible compiler])
fi
AC_PROG_CPP
AX_PTHREAD(,[AC_MSG_ERROR([Could not configure pthreads support])])
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
CC="$PTHREAD_CC"
# Checks for libtool
LT_INIT([disable-static])
AC_PROG_INSTALL
AC_PROG_LIBTOOL
AC_PROG_MAKE_SET
# Checks for header files.
AC_HEADER_STDC
# Checks for C sources
AC_CHECK_FUNCS([strdup])
AC_C_INLINE
AC_C_RESTRICT
AC_FUNC_MALLOC
AC_TYPE_SIZE_T
AC_TYPE_UINT32_T
# backwards compat with older pkg-config
# - pull in AC_DEFUN from pkg.m4
m4_ifndef([PKG_CHECK_VAR], [
# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
# -------------------------------------------
# Retrieves the value of the pkg-config variable for the given module.
AC_DEFUN([PKG_CHECK_VAR],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
_PKG_CONFIG([$1], [variable="][$3]["], [$2])
AS_VAR_COPY([$1], [pkg_cv_][$1])
AS_VAR_IF([$1], [""], [$5], [$4])dnl
])# PKG_CHECK_VAR
])
PKG_CHECK_MODULES([libvarnishapi], [varnishapi])
PKG_CHECK_VAR([LIBVARNISHAPI_PREFIX], [varnishapi], [prefix])
PKG_CHECK_VAR([LIBVARNISHAPI_DATAROOTDIR], [varnishapi], [datarootdir])
PKG_CHECK_VAR([LIBVARNISHAPI_BINDIR], [varnishapi], [bindir])
PKG_CHECK_VAR([LIBVARNISHAPI_SBINDIR], [varnishapi], [sbindir])
AC_SUBST([LIBVARNISHAPI_DATAROOTDIR])
# Varnish include files tree
VARNISH_VMOD_INCLUDES
VARNISH_VMOD_DIR
VARNISH_VMODTOOL
# inherit the prefix from Varnish.
# acessing ac_ variable because AC_PREFIX_DEFAULT acts too early
ac_default_prefix=$LIBVARNISHAPI_PREFIX
AC_PATH_PROG([VARNISHTEST], [varnishtest], [],
[$LIBVARNISHAPI_BINDIR:$LIBVARNISHAPI_SBINDIR:$PATH])
AC_PATH_PROG([VARNISHD], [varnishd], [],
[$LIBVARNISHAPI_SBINDIR:$LIBVARNISHAPI_BINDIR:$PATH])
# Check for rst utilities
AC_CHECK_PROGS(RST2MAN, [rst2man rst2man.py], "no")
if test "x$RST2MAN" = "xno"; then
AC_MSG_WARN([rst2man not found - not building man pages])
fi
AM_CONDITIONAL(HAVE_RST2MAN, [test "x$RST2MAN" != "xno"])
## Build for all pcre2 libs found via pkg-config, except for those
## excluded with a --without-X configure option.
PKG_CHECK_EXISTS([libpcre2-8], [have_lib8=yes], [have_lib8=no])
PKG_CHECK_EXISTS([libpcre2-16], [have_lib16=yes], [have_lib16=no])
PKG_CHECK_EXISTS([libpcre2-32], [have_lib32=yes], [have_lib32=no])
# Fail if none of the pcre2 libs can be found
AS_IF([test "x$have_lib8" != "xyes"], [
AS_IF([test "x$have_lib16" != "xyes"], [
AS_IF([test "x$have_lib32" != "xyes"],
[AC_MSG_ERROR([Could not find any pcre2 lib via pkg-config])]
)],
)]
)
AC_ARG_WITH([libpcre2-8], [
AS_HELP_STRING([--without-libpcre2-8],
[disable the pcre2 8-bit lib (enabled by default if present)])
])
AC_ARG_WITH([libpcre2-16], [
AS_HELP_STRING([--without-libpcre2-16],
[disable the pcre2 16-bit lib (enabled by default if present)])
])
AC_ARG_WITH([libpcre2-32], [
AS_HELP_STRING([--without-libpcre2-32],
[disable the pcre2 32-bit lib (enabled by default if present)])
])
# Fail if a --with option explicitly chose a lib that is not present
AS_IF([test "x$with_libpcre2_8" = "xyes"], [
AS_IF([test "x$have_lib8" != "xyes"],
[AC_MSG_ERROR([libpcre2-8 not found via pkg-config])]
)]
)
AS_IF([test "x$with_libpcre2_16" = "xyes"], [
AS_IF([test "x$have_lib16" != "xyes"],
[AC_MSG_ERROR([libpcre2-16 not found via pkg-config])]
)]
)
AS_IF([test "x$with_libpcre2_32" = "xyes"], [
AS_IF([test "x$have_lib32" != "xyes"],
[AC_MSG_ERROR([libpcre2-32 not found via pkg-config])]
)]
)
# Set up use of the pcre2 libs
PCRE2_CFLAGS=""
PCRE2_LIBS=""
AS_IF([test "x$have_lib8" != "xno"], [
AS_IF([test "x$with_libpcre2_8" != "xno"], [
PKG_CHECK_MODULES([PCRE2_8], [libpcre2-8])
AC_SUBST([PCRE2_8_CFLAGS])
AC_SUBST([PCRE2_8_LIBS])
PCRE2_CFLAGS=${PCRE2_8_CFLAGS}
PCRE2_LIBS=${PCRE2_8_LIBS}
AC_DEFINE([HAVE_PCRE2_8], [1],
[Define to 1 if the 8-bit pcre2 library is used])
])
])
AS_IF([test "x$have_lib16" != "xno"], [
AS_IF([test "x$with_libpcre2_16" != "xno"], [
PKG_CHECK_MODULES([PCRE2_16], [libpcre2-16])
AC_SUBST([PCRE2_16_CFLAGS])
AC_SUBST([PCRE2_16_LIBS])
PCRE2_CFLAGS="${PCRE2_CFLAGS} ${PCRE2_16_CFLAGS}"
PCRE2_LIBS="${PCRE2_LIBS} ${PCRE2_16_LIBS}"
AC_DEFINE([HAVE_PCRE2_16], [1],
[Define to 1 if the 16-bit pcre2 library is used])
])
])
AS_IF([test "x$have_lib32" != "xno"], [
AS_IF([test "x$with_libpcre2_32" != "xno"], [
PKG_CHECK_MODULES([PCRE2_32], [libpcre2-32])
AC_SUBST([PCRE2_32_CFLAGS])
AC_SUBST([PCRE2_32_LIBS])
PCRE2_CFLAGS="${PCRE2_CFLAGS} ${PCRE2_32_CFLAGS}"
PCRE2_LIBS="${PCRE2_LIBS} ${PCRE2_32_LIBS}"
AC_DEFINE([HAVE_PCRE2_32], [1],
[Define to 1 if the 32-bit pcre2 library is used])
])
])
AS_IF([test -z "$PCRE2_LIBS"], [
AC_MSG_ERROR([You must enable at least one available pcre2 lib])
])
AC_SUBST([PCRE2_CFLAGS])
AC_SUBST([PCRE2_LIBS])
# --enable-stack-protector
AC_ARG_ENABLE(stack-protector,
AS_HELP_STRING([--enable-stack-protector],[enable stack protector (default is YES)]),
[],
[enable_stack_protector=yes])
if test "x$enable_stack_protector" != "xno"; then
AX_CHECK_COMPILE_FLAG([-fstack-protector],
AX_CHECK_LINK_FLAG([-fstack-protector],
[CFLAGS="${CFLAGS} -fstack-protector"], [], []),
[], [])
fi
# --enable-debugging
AC_ARG_ENABLE(debugging,
AS_HELP_STRING([--enable-debugging],[enable debugging (default is NO)]),
[],
[enable_debugging=no])
# AC_PROG_CC sets CFLAGS to '-g -O2' unless it is already set, so
# there's no need to add -g. Disable or change by explicitly setting
# CFLAGS. If this option is enabled, then -Og or -O0 becomes the last
# optimization option, and hence takes precedence.
if test "x$enable_debugging" != "xno"; then
CFLAGS="${CFLAGS} -fno-inline"
AX_CHECK_COMPILE_FLAG([-Og],
[CFLAGS="${CFLAGS} -Og"],
[CFLAGS="${CFLAGS} -O0"],
[])
fi
AC_CONFIG_FILES([
Makefile
src/Makefile
])
AC_OUTPUT
AM_CPPFLAGS = @VMOD_INCLUDES@ -Wall -Werror -Wextra -std=c99 @PCRE2_CFLAGS@
vmoddir = @VMOD_DIR@
vmod_LTLIBRARIES = libvmod_pcre2.la
libvmod_pcre2_la_LDFLAGS = -module -export-dynamic -avoid-version -shared
libvmod_pcre2_la_SOURCES = \
vmod_pcre2.c \
vmod_pcre2.h \
pcre2_compat.h
nodist_libvmod_pcre2_la_SOURCES = \
vcc_if.c \
vcc_if.h
libvmod_pcre2_la_LIBADD = @PCRE2_LIBS@
vmod_pcre2.lo: vcc_if.c vcc_if.h
vcc_if.c: vcc_if.h
vcc_if.h vmod_pcre2.man.rst: @VMODTOOL@ $(top_srcdir)/src/vmod_pcre2.vcc
@VMODTOOL@ $(top_srcdir)/src/vmod_pcre2.vcc
VMOD_TESTS = $(top_srcdir)/src/tests/*.vtc
.PHONY: $(VMOD_TESTS)
$(top_srcdir)/src/tests/*.vtc: libvmod_pcre2.la
PATH=@LIBVARNISHAPI_SBINDIR@:$$PATH \
@VARNISHTEST@ -Dvmod_topbuild=$(abs_top_builddir) $@
check: $(VMOD_TESTS)
EXTRA_DIST = \
vmod_pcre2.vcc \
$(VMOD_TESTS)
CLEANFILES = \
$(builddir)/vcc_if.c \
$(builddir)/vcc_if.h \
$(builddir)/vmod_pcre2.rst \
$(builddir)/vmod_pcre2.man.rst
/*-
* Copyright 2017 UPLEX - Nils Goroll Systemoptimierung
* All rights reserved.
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "config.h"
#if !HAVE_PCRE2_8 && !HAVE_PCRE2_16 && !HAVE_PCRE2_32
#error "none of the 8-, 16- or 32-bit pcre2 libs specified in config.h"
#endif
#define PCRE2_CODE_UNIT_WIDTH 0
#include "pcre2.h"
#if HAVE_PCRE2_8
#define LIB_SMALLEST (LIB8)
#elif HAVE_PCRE2_16
#define LIB_SMALLEST (LIB16)
#elif HAVE_PCRE2_32
#define LIB_SMALLEST (LIB32)
#endif
typedef union {
#if HAVE_PCRE2_8
pcre2_code_8 *code8;
#endif
#if HAVE_PCRE2_16
pcre2_code_16 *code16;
#endif
#if HAVE_PCRE2_32
pcre2_code_32 *code32;
#endif
} pcre2_code_t;
typedef union {
#if HAVE_PCRE2_8
pcre2_compile_context_8 *ccontext8;
#endif
#if HAVE_PCRE2_16
pcre2_compile_context_16 *ccontext16;
#endif
#if HAVE_PCRE2_32
pcre2_compile_context_32 *ccontext32;
#endif
} pcre2_compile_context_t;
typedef struct {
#if HAVE_PCRE2_8
pcre2_general_context_8 *gcontext8;
#endif
#if HAVE_PCRE2_16
pcre2_general_context_16 *gcontext16;
#endif
#if HAVE_PCRE2_32
pcre2_general_context_32 *gcontext32;
#endif
} pcre2_general_context_t;
typedef union {
#if HAVE_PCRE2_8
pcre2_match_context_8 *mcontext8;
#endif
#if HAVE_PCRE2_16
pcre2_match_context_16 *mcontext16;
#endif
#if HAVE_PCRE2_32
pcre2_match_context_32 *mcontext32;
#endif
} pcre2_match_context_t;
typedef union {
#if HAVE_PCRE2_8
pcre2_match_data_8 *mdata8;
#endif
#if HAVE_PCRE2_16
pcre2_match_data_16 *mdata16;
#endif
#if HAVE_PCRE2_32
pcre2_match_data_32 *mdata32;
#endif
} pcre2_match_data_t;
static const int have_lib[_LIB_MAX] = {
[LIB8] = HAVE_PCRE2_8, [LIB16] = HAVE_PCRE2_16, [LIB32] = HAVE_PCRE2_32
};
static inline void
PCRE2_COMPILE_CONTEXT_CREATE(enum code_size codesz,
pcre2_compile_context_t *cctx)
{
switch(codesz) {
case LIB8:
#if HAVE_PCRE2_8
cctx->ccontext8 = pcre2_compile_context_create_8(NULL);
break;
#else
WRONG("8-bit lib not supported");
#endif
case LIB16:
#if HAVE_PCRE2_16
cctx->ccontext16 = pcre2_compile_context_create_16(NULL);
break;
#else
WRONG("16-bit lib not supported");
#endif
case LIB32:
#if HAVE_PCRE2_32
cctx->ccontext32 = pcre2_compile_context_create_32(NULL);
break;
#else
WRONG("32-bit lib not supported");
#endif
default:
WRONG("Illegal code size");
}
}
static inline void
PCRE2_COMPILE_CONTEXT_FREE(enum code_size codesz, pcre2_compile_context_t *cctx)
{
switch(codesz) {
case LIB8:
#if HAVE_PCRE2_8
pcre2_compile_context_free_8(cctx->ccontext8);
break;
#else
WRONG("8-bit lib not supported");
#endif
case LIB16:
#if HAVE_PCRE2_16
pcre2_compile_context_free_16(cctx->ccontext16);
break;
#else
WRONG("16-bit lib not supported");
#endif
case LIB32:
#if HAVE_PCRE2_32
pcre2_compile_context_free_32(cctx->ccontext32);
break;
#else
WRONG("32-bit lib not supported");
#endif
default:
WRONG("Illegal code size");
}
}
static inline int
PCRE2_COMPILE(enum code_size codesz, pcre2_code_t *code, VCL_STRING pattern,
PCRE2_SIZE length, uint32_t options, int *err_code,
PCRE2_SIZE *err_offset, pcre2_compile_context_t *cctx)
{
switch(codesz) {
case LIB8:
#if HAVE_PCRE2_8
code->code8 = pcre2_compile_8((PCRE2_SPTR8)pattern, length,
options, err_code, err_offset,
cctx->ccontext8);
return code->code8 == NULL;
#else
WRONG("8-bit lib not supported");
#endif
case LIB16:
#if HAVE_PCRE2_16
code->code16 = pcre2_compile_16((PCRE2_SPTR16)pattern, length,
options, err_code, err_offset,
cctx->ccontext16);
return code->code16 == NULL;
#else
WRONG("16-bit lib not supported");
#endif
case LIB32:
#if HAVE_PCRE2_32
code->code32 = pcre2_compile_32((PCRE2_SPTR32)pattern, length,
options, err_code, err_offset,
cctx->ccontext32);
return code->code32 == NULL;
#else
WRONG("32-bit lib not supported");
#endif
default:
WRONG("Illegal code size");
}
}
static inline int
PCRE2_JIT_COMPILE(enum code_size codesz, pcre2_code_t *code, uint32_t options)
{
switch(codesz) {
case LIB8:
#if HAVE_PCRE2_8
return pcre2_jit_compile_8(code->code8, options);
#else
WRONG("8-bit lib not supported");
#endif
case LIB16:
#if HAVE_PCRE2_16
return pcre2_jit_compile_16(code->code16, options);
#else
WRONG("16-bit lib not supported");
#endif
case LIB32:
#if HAVE_PCRE2_32
return pcre2_jit_compile_32(code->code32, options);
#else
WRONG("32-bit lib not supported");
#endif
default:
WRONG("Illegal code size");
}
}
static inline void
PCRE2_CODE_FREE(enum code_size codesz, pcre2_code_t *code)
{
switch(codesz) {
case LIB8:
#if HAVE_PCRE2_8
pcre2_code_free_8(code->code8);
#else
WRONG("8-bit lib not supported");
#endif
case LIB16:
#if HAVE_PCRE2_16
pcre2_code_free_16(code->code16);
#else
WRONG("16-bit lib not supported");
#endif
case LIB32:
#if HAVE_PCRE2_32
pcre2_code_free_32(code->code32);
#else
WRONG("32-bit lib not supported");
#endif
default:
WRONG("Illegal code size");
}
}
static inline int
PCRE2_MATCH(enum code_size codesz, pcre2_code_t *code, VCL_STRING subject,
PCRE2_SIZE length, PCRE2_SIZE start_offset, uint32_t options,
pcre2_match_data_t *mdata, pcre2_match_context_t *mctx)
{
switch(codesz) {
case LIB8:
#if HAVE_PCRE2_8
return pcre2_match_8(code->code8, (PCRE2_SPTR8)subject,
length, start_offset, options,
mdata->mdata8, mctx->mcontext8);
#else
WRONG("8-bit lib not supported");
#endif
case LIB16:
#if HAVE_PCRE2_16
return pcre2_match_16(code->code16, (PCRE2_SPTR16)subject,
length, start_offset, options,
mdata->mdata16, mctx->mcontext16);
#else
WRONG("16-bit lib not supported");
#endif
case LIB32:
#if HAVE_PCRE2_32
return pcre2_match_32(code->code32, (PCRE2_SPTR32)subject,
length, start_offset, options,
mdata->mdata32, mctx->mcontext32);
#else
WRONG("32-bit lib not supported");
#endif
default:
WRONG("Illegal code size");
}
}
static inline int
PCRE2_GENERAL_CONTEXT_CREATE(pcre2_general_context_t *gctx,
void *(*private_malloc)(PCRE2_SIZE, void *),
void (*private_free)(void *, void *), void *ws)
{
#if HAVE_PCRE2_8
VSL(SLT_Debug, 0, "gctx_create8 gctx = %p, malloc = %p, free = %p",
gctx, private_malloc, private_free);
gctx->gcontext8 = pcre2_general_context_create_8(private_malloc,
private_free, ws);
VSL(SLT_Debug, 0, "gctx_create8 returned gcontext8 = %p",
gctx->gcontext8);
if (gctx->gcontext8 == NULL)
return -1;
#endif
#if HAVE_PCRE2_16
VSL(SLT_Debug, 0, "gctx_create16 gctx = %p, malloc = %p, free = %p",
gctx, private_malloc, private_free);
gctx->gcontext16 = pcre2_general_context_create_16(private_malloc,
private_free, ws);
VSL(SLT_Debug, 0, "gctx_create16 returned gcontext16 = %p",
gctx->gcontext16);
if (gctx->gcontext16 == NULL)
return -1;
#endif
#if HAVE_PCRE2_32
VSL(SLT_Debug, 0, "gctx_create32 gctx = %p, malloc = %p, free = %p",
gctx, private_malloc, private_free);
gctx->gcontext32 = pcre2_general_context_create_32(private_malloc,
private_free, ws);
VSL(SLT_Debug, 0, "gctx_create32 returned gcontext32 = %p",
gctx->gcontext32);
if (gctx->gcontext32 == NULL)
return -1;
#endif
return 0;
}
static inline int
PCRE2_MATCH_CONTEXT_CREATE(enum code_size codesz, pcre2_match_context_t *mctx,
pcre2_general_context_t *gctx)
{
switch(codesz) {
case LIB8:
#if HAVE_PCRE2_8
VSL(SLT_Debug, 0, "mctx_create mcontext8 = %p, gcontext8 = %p",
mctx->mcontext8, gctx->gcontext8);
mctx->mcontext8 = pcre2_match_context_create_8(gctx->gcontext8);
VSL(SLT_Debug, 0, "mctx_create returned mcontext8 = %p",
mctx->mcontext8);
return mctx->mcontext8 == NULL;
#else
WRONG("8-bit lib not supported");
#endif
case LIB16:
#if HAVE_PCRE2_16
mctx->mcontext16
= pcre2_match_context_create_16(gctx->gcontext16);
return mctx->mcontext16 == NULL;
#else
WRONG("16-bit lib not supported");
#endif
case LIB32:
#if HAVE_PCRE2_32
mctx->mcontext32
= pcre2_match_context_create_32(gctx->gcontext32);
return mctx->mcontext32 == NULL;
#else
WRONG("32-bit lib not supported");
#endif
default:
WRONG("Illegal code size");
}
}
static inline int
PCRE2_MATCH_DATA_CREATE_FROM_PATTERN(enum code_size codesz,
pcre2_match_data_t *mdata,
pcre2_code_t *code,
pcre2_general_context_t *gctx)
{
switch(codesz) {
case LIB8:
#if HAVE_PCRE2_8
mdata->mdata8
= pcre2_match_data_create_from_pattern_8(code->code8,
gctx->gcontext8);
return mdata->mdata8 == NULL;
#else
WRONG("8-bit lib not supported");
#endif
case LIB16:
#if HAVE_PCRE2_16
mdata->mdata16
= pcre2_match_data_create_from_pattern_16(code->code16,
gctx->gcontext16);
return mdata->mdata16 == NULL;
#else
WRONG("16-bit lib not supported");
#endif
case LIB32:
#if HAVE_PCRE2_32
mdata->mdata32
= pcre2_match_data_create_from_pattern_32(code->code32,
gctx->gcontext32);
return mdata->mdata8 == NULL;
#else
WRONG("32-bit lib not supported");
#endif
default:
WRONG("Illegal code size");
}
}
static inline int
PCRE2_GET_ERROR_MESSAGE(enum code_size codesz, int errorcode, char *buf,
unsigned bytes)
{
switch(codesz) {
case LIB8:
#if HAVE_PCRE2_8
return pcre2_get_error_message_8(errorcode,
(PCRE2_UCHAR8 *)buf, bytes)
+ 1;
#else
WRONG("8-bit lib not supported");
#endif
case LIB16:
#if HAVE_PCRE2_16
return pcre2_get_error_message_16(errorcode,
(PCRE2_UCHAR16 *)buf,
bytes / 2) * 2 + 1;
#else
WRONG("16-bit lib not supported");
#endif
case LIB32:
#if HAVE_PCRE2_32
return pcre2_get_error_message_32(errorcode,
(PCRE2_UCHAR32 *)buf,
bytes / 4) * 4 + 1;
#else
WRONG("32-bit lib not supported");
#endif
default:
WRONG("Illegal code size");
}
}
static inline int
PCRE2_SET_BSR(enum code_size codesz, pcre2_compile_context_t *cctx,
uint32_t value)
{
switch(codesz) {
case LIB8:
#if HAVE_PCRE2_8
return pcre2_set_bsr_8(cctx->ccontext8, value);
#else
WRONG("8-bit lib not supported");
#endif
case LIB16:
#if HAVE_PCRE2_16
return pcre2_set_bsr_16(cctx->ccontext16, value);
#else
WRONG("16-bit lib not supported");
#endif
case LIB32:
#if HAVE_PCRE2_32
return pcre2_set_bsr_32(cctx->ccontext32, value);
#else
WRONG("32-bit lib not supported");
#endif
default:
WRONG("Illegal code size");
}
}
static inline int
PCRE2_SET_MAX_PATTERN_LENGTH(enum code_size codesz,
pcre2_compile_context_t *cctx, uint32_t value)
{
switch(codesz) {
case LIB8:
#if HAVE_PCRE2_8
return pcre2_set_max_pattern_length_8(cctx->ccontext8, value);
#else
WRONG("8-bit lib not supported");
#endif
case LIB16:
#if HAVE_PCRE2_16
return pcre2_set_max_pattern_length_16(cctx->ccontext16, value);
#else
WRONG("16-bit lib not supported");
#endif
case LIB32:
#if HAVE_PCRE2_32
return pcre2_set_max_pattern_length_32(cctx->ccontext32, value);
#else
WRONG("32-bit lib not supported");
#endif
default:
WRONG("Illegal code size");
}
}
static inline int
PCRE2_SET_NEWLINE(enum code_size codesz, pcre2_compile_context_t *cctx,
uint32_t value)
{
switch(codesz) {
case LIB8:
#if HAVE_PCRE2_8
return pcre2_set_newline_8(cctx->ccontext8, value);
#else
WRONG("8-bit lib not supported");
#endif
case LIB16:
#if HAVE_PCRE2_16
return pcre2_set_newline_16(cctx->ccontext16, value);
#else
WRONG("16-bit lib not supported");
#endif
case LIB32:
#if HAVE_PCRE2_32
return pcre2_set_newline_32(cctx->ccontext32, value);
#else
WRONG("32-bit lib not supported");
#endif
default:
WRONG("Illegal code size");
}
}
static inline int
PCRE2_SET_PARENS_NEST_LIMIT(enum code_size codesz,
pcre2_compile_context_t *cctx, uint32_t value)
{
switch(codesz) {
case LIB8:
#if HAVE_PCRE2_8
return pcre2_set_parens_nest_limit_8(cctx->ccontext8, value);
#else
WRONG("8-bit lib not supported");
#endif
case LIB16:
#if HAVE_PCRE2_16
return pcre2_set_parens_nest_limit_16(cctx->ccontext16, value);
#else
WRONG("16-bit lib not supported");
#endif
case LIB32:
#if HAVE_PCRE2_32
return pcre2_set_parens_nest_limit_32(cctx->ccontext32, value);
#else
WRONG("32-bit lib not supported");
#endif
default:
WRONG("Illegal code size");
}
}
static inline int
PCRE2_SET_MATCH_LIMIT(enum code_size codesz, pcre2_match_context_t *mctx,
uint32_t value)
{
switch(codesz) {
case LIB8:
#if HAVE_PCRE2_8
return pcre2_set_match_limit_8(mctx->mcontext8, value);
#else
WRONG("8-bit lib not supported");
#endif
case LIB16:
#if HAVE_PCRE2_16
return pcre2_set_match_limit_16(mctx->mcontext16, value);
#else
WRONG("16-bit lib not supported");
#endif
case LIB32:
#if HAVE_PCRE2_32
return pcre2_set_match_limit_32(mctx->mcontext32, value);
#else
WRONG("32-bit lib not supported");
#endif
default:
WRONG("Illegal code size");
}
}
static inline int
PCRE2_SET_OFFSET_LIMIT(enum code_size codesz, pcre2_match_context_t *mctx,
uint32_t value)
{
switch(codesz) {
case LIB8:
#if HAVE_PCRE2_8
return pcre2_set_offset_limit_8(mctx->mcontext8, value);
#else
WRONG("8-bit lib not supported");
#endif
case LIB16:
#if HAVE_PCRE2_16
return pcre2_set_offset_limit_16(mctx->mcontext16, value);
#else
WRONG("16-bit lib not supported");
#endif
case LIB32:
#if HAVE_PCRE2_32
return pcre2_set_offset_limit_32(mctx->mcontext32, value);
#else
WRONG("32-bit lib not supported");
#endif
default:
WRONG("Illegal code size");
}
}
static inline int
PCRE2_SET_RECURSION_LIMIT(enum code_size codesz, pcre2_match_context_t *mctx,
uint32_t value)
{
switch(codesz) {
case LIB8:
#if HAVE_PCRE2_8
return pcre2_set_recursion_limit_8(mctx->mcontext8, value);
#else
WRONG("8-bit lib not supported");
#endif
case LIB16:
#if HAVE_PCRE2_16
return pcre2_set_recursion_limit_16(mctx->mcontext16, value);
#else
WRONG("16-bit lib not supported");
#endif
case LIB32:
#if HAVE_PCRE2_32
return pcre2_set_recursion_limit_32(mctx->mcontext32, value);
#else
WRONG("32-bit lib not supported");
#endif
default:
WRONG("Illegal code size");
}
}
static inline int
PCRE2_CONFIG(enum code_size codesz, uint32_t what, void *where)
{
switch(codesz) {
case LIB8:
#if HAVE_PCRE2_8
return pcre2_config_8(what, where);
#else
WRONG("8-bit lib not supported");
#endif
case LIB16:
#if HAVE_PCRE2_16
return pcre2_config_16(what, where);
#else
WRONG("16-bit lib not supported");
#endif
case LIB32:
#if HAVE_PCRE2_32
return pcre2_config_32(what, where);
#else
WRONG("32-bit lib not supported");
#endif
default:
WRONG("Illegal code size");
}
}
# looks like -*- vcl -*-
varnishtest "vcl.use and .discard, and version string"
server s1 {} -start
varnish v1 -vcl+backend {
import pcre2 from "${vmod_topbuild}/src/.libs/libvmod_pcre2.so";
} -start
varnish v1 -vcl+backend {}
varnish v1 -cli "vcl.list"
varnish v1 -cli "vcl.use vcl1"
varnish v1 -cli "vcl.use vcl2"
varnish v1 -cli "vcl.use vcl1"
varnish v1 -cli "vcl.show vcl1"
varnish v1 -cli "vcl.use vcl2"
varnish v1 -cli "vcl.discard vcl1"
varnish v1 -cli "vcl.list"
varnish v1 -vcl {
import pcre2 from "${vmod_topbuild}/src/.libs/libvmod_pcre2.so";
backend b { .host = "${bad_ip}"; }
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
set resp.http.x-version = pcre2.version();
if (!resp.http.x-version) {
set resp.status = 500;
}
return(deliver);
}
}
client c1 {
txreq -url "/"
rxresp
expect resp.status == 200
expect resp.http.x-version ~ "^.+$"
} -run
# looks like -*- vcl -*-
varnishtest "regex constructor"
varnish v1 -vcl {
import pcre2 from "${vmod_topbuild}/src/.libs/libvmod_pcre2.so";
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new r = pcre2.regex("foo");
}
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
set resp.http.fmatch = r.match("foo");
set resp.http.gmatch = r.match("goo");
}
} -start
client c1 {
txreq
rxresp
expect resp.http.fmatch == "true"
expect resp.http.gmatch == "false"
} -run
# looks like -*- vcl -*-
varnishtest "functions config_bool, _int and _str"
varnish v1 -vcl {
import pcre2 from "${vmod_topbuild}/src/.libs/libvmod_pcre2.so";
backend b { .host = "${bad_ip}"; }
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
set resp.http.jit = pcre2.config_bool(JIT);
set resp.http.stackrecurse = pcre2.config_bool(STACKRECURSE);
set resp.http.unicode = pcre2.config_bool(UNICODE);
set resp.http.bsr = pcre2.config_str(BSR);
set resp.http.jittarget = pcre2.config_str(JITTARGET);
set resp.http.newline = pcre2.config_str(NEWLINE);
set resp.http.unicode-version
= pcre2.config_str(UNICODE_VERSION);
set resp.http.version = pcre2.config_str(VERSION);
set resp.http.linksize = pcre2.config_int(LINKSIZE);
set resp.http.matchlimit = pcre2.config_int(MATCHLIMIT);
set resp.http.parenslimit = pcre2.config_int(PARENSLIMIT);
set resp.http.recursionlimit = pcre2.config_int(RECURSIONLIMIT);
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.jit ~ "^(true|false)$"
expect resp.http.stackrecurse ~ "^(true|false)$"
expect resp.http.unicode ~ "^(true|false)$"
expect resp.http.bsr ~ "^(UNICODE|ANYCRLF)$"
expect resp.http.jittarget ~ ".+"
expect resp.http.newline ~ "^(CR|LF|CRLF|ANY|ANYCRLF)$"
expect resp.http.unicode-version ~ ".+"
expect resp.http.version ~ ".+"
expect resp.http.linksize ~ "^\\d+$"
expect resp.http.matchlimit ~ "^\\d+$"
expect resp.http.parenslimit ~ "^\\d+$"
expect resp.http.recursionlimit ~ "^\\d+$"
} -run
varnish v1 -vcl {
import pcre2 from "${vmod_topbuild}/src/.libs/libvmod_pcre2.so";
backend b { .host = "${bad_ip}"; }
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
set resp.http.jit = pcre2.config_bool(JIT, lib=LIB8);
set resp.http.stackrecurse = pcre2.config_bool(STACKRECURSE);
set resp.http.unicode = pcre2.config_bool(UNICODE);
set resp.http.bsr = pcre2.config_str(BSR);
set resp.http.jittarget = pcre2.config_str(JITTARGET);
set resp.http.newline = pcre2.config_str(NEWLINE);
set resp.http.unicode-version
= pcre2.config_str(UNICODE_VERSION);
set resp.http.version = pcre2.config_str(VERSION);
set resp.http.linksize = pcre2.config_int(LINKSIZE);
set resp.http.matchlimit = pcre2.config_int(MATCHLIMIT);
set resp.http.parenslimit = pcre2.config_int(PARENSLIMIT);
set resp.http.recursionlimit = pcre2.config_int(RECURSIONLIMIT);
}
}
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.jit ~ "^(true|false)$"
expect resp.http.stackrecurse ~ "^(true|false)$"
expect resp.http.unicode ~ "^(true|false)$"
expect resp.http.bsr ~ "^(UNICODE|ANYCRLF)$"
expect resp.http.jittarget ~ ".+"
expect resp.http.newline ~ "^(CR|LF|CRLF|ANY|ANYCRLF)$"
expect resp.http.unicode-version ~ ".+"
expect resp.http.version ~ ".+"
expect resp.http.linksize ~ "^\\d+$"
expect resp.http.matchlimit ~ "^\\d+$"
expect resp.http.parenslimit ~ "^\\d+$"
expect resp.http.recursionlimit ~ "^\\d+$"
} -run
/*-
* Copyright 2017 UPLEX - Nils Goroll Systemoptimierung
* All rights reserved.
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "config.h"
#include <stdint.h>
#include <string.h>
#include "vcl.h"
#include "vrt.h"
#include "vas.h"
#include "vdef.h"
#include "cache/cache.h"
#include "vcc_if.h"
/* XXX enum in a separate .h? */
enum code_size {
LIB8 = 0,
LIB16,
LIB32,
_LIB_MAX
};
#include "pcre2_compat.h"
#define ERR(ctx, msg) \
errmsg((ctx), "vmod pcre2 error: " msg)
#define VERR(ctx, fmt, ...) \
errmsg((ctx), "vmod pcre2 error: " fmt, __VA_ARGS__)
#define VERRNOMEM(ctx, fmt, ...) \
VERR((ctx), fmt ", out of space", __VA_ARGS__)
#define ERRNOMEM(ctx, msg) \
ERR((ctx), msg ", out of space")
#define INIT(ctx) (((ctx)->method & VCL_MET_INIT) != 0)
struct vmod_pcre2_regex {
unsigned magic;
#define VMOD_PCRE2_REGEX_MAGIC 0x3adb2a78
pcre2_code_t code;
char *vcl_name;
enum code_size codesz;
};
#if 0
/* PRIV_CALL scope for match */
struct match_call {
unsigned magic;
#define VMOD_PCRE2_MATCH_CALL_MAGIC 0x60e5bd33
pcre2_match_context_t mctx;
uint32_t options;
};
#endif
static const int code_size[_LIB_MAX] = {
[LIB8] = 8, [LIB16] = 16, [LIB32] = 32
};
static int have_jit[_LIB_MAX] = { 0 };
void
errmsg(VRT_CTX, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
if (ctx->method == VCL_MET_INIT) {
AN(ctx->msg);
VSB_vprintf(ctx->msg, fmt, args);
VRT_handling(ctx, VCL_RET_FAIL);
}
else if (ctx->vsl)
VSLbv(ctx->vsl, SLT_VCL_Error, fmt, args);
else
/* Should this ever happen in vcl_fini() ... */
VSL(SLT_VCL_Error, 0, fmt, args);
va_end(args);
}
static inline void
WS_Allocated(struct ws * const restrict ws, const void * const restrict ptr,
const size_t len)
{
assert((char *)ptr >= ws->s && ((char *)ptr + len) <= ws->f);
}
static inline enum code_size
decode_lib_enum(VCL_ENUM libs)
{
if (libs == NULL)
return LIB_SMALLEST;
else if (strcmp(libs, "LIB8") == 0)
return LIB8;
else if (strcmp(libs, "LIB16") == 0)
return LIB16;
else if (strcmp(libs, "LIB32") == 0)
return LIB32;
else
WRONG("Illegal lib enum");
}
/* Event function */
int __match_proto__(vmod_event_f)
event(VRT_CTX, struct vmod_priv *priv, enum vcl_event_e e)
{
(void) ctx;
(void) priv;
if (e == VCL_EVENT_LOAD) {
int ret;
uint32_t where;
if (have_lib[LIB8]) {
ret = PCRE2_CONFIG(LIB8, PCRE2_CONFIG_JIT, &where);
assert(ret >= 0);
have_jit[LIB8] = where;
}
if (have_lib[LIB16]) {
ret = PCRE2_CONFIG(LIB16, PCRE2_CONFIG_JIT, &where);
assert(ret >= 0);
have_jit[LIB16] = where;
}
if (have_lib[LIB32]) {
ret = PCRE2_CONFIG(LIB32, PCRE2_CONFIG_JIT, &where);
assert(ret >= 0);
have_jit[LIB32] = where;
}
}
return 0;
}
/* Object regex */
static void *
ws_malloc(PCRE2_SIZE sz, void *ws)
{
void *p;
VSL(SLT_Debug, 0, "sz = %zu, ws = %p", sz, ws);
WS_Assert(ws);
VSL(SLT_Debug, 0, "WS_Asserted");
//return WS_Alloc(ws, sz);
p = WS_Alloc(ws, sz);
VSL(SLT_Debug, 0, "WS_Alloced %p", p);
return p;
}
static void
ws_free(void *ptr, void *ws)
{
VSL(SLT_Debug, 0, "free ptr = %p, ws = %p", ptr, ws);
WS_Assert(ws);
WS_Allocated(ws, ptr, 0);
}
VCL_VOID
vmod_regex__init(VRT_CTX, struct vmod_pcre2_regex **regexp,
const char *vcl_name, VCL_STRING pattern, VCL_ENUM libs,
VCL_BOOL allow_empty_class, VCL_BOOL anchored, VCL_ENUM bsrs,
VCL_BOOL alt_bsux, VCL_BOOL alt_circumflex,
VCL_BOOL alt_verbnames, VCL_BOOL caseless,
VCL_BOOL dollar_endonly, VCL_BOOL dotall, VCL_BOOL dupnames,
VCL_BOOL extended, VCL_BOOL firstline, VCL_STRING locale,
VCL_BOOL match_unset_backref, VCL_INT max_pattern_len,
VCL_BOOL multiline, VCL_BOOL never_backslash_c,
VCL_BOOL never_ucp, VCL_BOOL never_utf, VCL_ENUM newlines,
VCL_BOOL no_auto_capture, VCL_BOOL no_auto_possess,
VCL_BOOL no_dotstar_anchor, VCL_BOOL no_start_optimize,
VCL_BOOL no_utf_check, VCL_INT parens_nest_limit,
VCL_BOOL ucp, VCL_BOOL ungreedy, VCL_BOOL use_offset_limit,
VCL_BOOL utf)
{
struct vmod_pcre2_regex *regex;
enum code_size codesz;
pcre2_code_t code;
pcre2_compile_context_t ccontext;
uint32_t options = 0, val;
int ret, err_code = 0;
PCRE2_SIZE err_offset;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
AN(regexp);
AZ(*regexp);
AN(vcl_name);
if (pattern == NULL) {
VERR(ctx, "pattern is NULL in %s constructor", vcl_name);
return;
}
codesz = decode_lib_enum(libs);
if (!have_lib[codesz]) {
VERR(ctx, "%d-bit library not supported in %s constructor",
code_size[codesz], vcl_name);
return;
}
PCRE2_COMPILE_CONTEXT_CREATE(codesz, &ccontext);
if (bsrs != NULL) {
if (strcmp("ANYCRLF", bsrs) == 0)
val = PCRE2_BSR_ANYCRLF;
else if (strcmp("UNICODE", bsrs) == 0)
val = PCRE2_BSR_UNICODE;
else
WRONG("Illegal bsr enum value");
ret = PCRE2_SET_BSR(codesz, &ccontext, val);
AZ(ret);
}
if (locale != NULL) {
VERR(ctx, "locales not implemented yet in %s constructor",
vcl_name);
return;
}
if (max_pattern_len != 0) {
ret = PCRE2_SET_MAX_PATTERN_LENGTH(codesz, &ccontext,
(PCRE2_SIZE)max_pattern_len);
AZ(ret);
}
if (newlines != NULL) {
if (strcmp("CR", newlines) == 0)
val = PCRE2_NEWLINE_CR;
else if (strcmp("LF", newlines) == 0)
val = PCRE2_NEWLINE_LF;
else if (strcmp("CRLF", newlines) == 0)
val = PCRE2_NEWLINE_CRLF;
else if (strcmp("ANYCRLF", newlines) == 0)
val = PCRE2_NEWLINE_ANYCRLF;
else if (strcmp("ANY", newlines) == 0)
val = PCRE2_NEWLINE_ANY;
else
WRONG("Illegal newline enum value");
ret = PCRE2_SET_NEWLINE(codesz, &ccontext, val);
AZ(ret);
}
if (parens_nest_limit != 0) {
ret = PCRE2_SET_PARENS_NEST_LIMIT(codesz, &ccontext,
(uint32_t)parens_nest_limit);
AZ(ret);
}
/* XXX check illegal combinations such as never_ucp && ucp ... ? */
if (anchored)
options |= PCRE2_ANCHORED;
if (allow_empty_class)
options |= PCRE2_ALLOW_EMPTY_CLASS;
if (alt_bsux)
options |= PCRE2_ALT_BSUX;
if (alt_circumflex)
options |= PCRE2_ALT_CIRCUMFLEX;
if (alt_verbnames)
options |= PCRE2_ALT_VERBNAMES;
if (caseless)
options |= PCRE2_CASELESS;
if (dollar_endonly)
options |= PCRE2_DOLLAR_ENDONLY;
if (dotall)
options |= PCRE2_DOTALL;
if (dupnames)
options |= PCRE2_DUPNAMES;
if (extended)
options |= PCRE2_EXTENDED;
if (firstline)
options |= PCRE2_FIRSTLINE;
if (match_unset_backref)
options |= PCRE2_MATCH_UNSET_BACKREF;
if (multiline)
options |= PCRE2_MULTILINE;
if (never_backslash_c)
options |= PCRE2_NEVER_BACKSLASH_C;
if (never_ucp)
options |= PCRE2_NEVER_UCP;
if (never_utf)
options |= PCRE2_NEVER_UTF;
if (no_auto_capture)
options |= PCRE2_NO_AUTO_CAPTURE;
if (no_auto_possess)
options |= PCRE2_NO_AUTO_POSSESS;
if (no_dotstar_anchor)
options |= PCRE2_NO_DOTSTAR_ANCHOR;
if (no_start_optimize)
options |= PCRE2_NO_START_OPTIMIZE;
if (no_utf_check)
options |= PCRE2_NO_UTF_CHECK;
if (ucp)
options |= PCRE2_UCP;
if (ungreedy)
options |= PCRE2_UNGREEDY;
if (use_offset_limit)
options |= PCRE2_USE_OFFSET_LIMIT;
if (utf)
options |= PCRE2_UTF;
/* XXX set the length via parameter */
ret = PCRE2_COMPILE(codesz, &code, pattern, PCRE2_ZERO_TERMINATED,
options, &err_code, &err_offset, &ccontext);
if (ret != 0) {
char *buf = WS_Snapshot(ctx->ws);
unsigned bytes = WS_Reserve(ctx->ws, 0);
ret = PCRE2_GET_ERROR_MESSAGE(codesz, err_code, buf, bytes);
if (ret == PCRE2_ERROR_BADDATA) {
WS_ReleaseP(ctx->ws, buf);
VERR(ctx, "Cannot compile '%s' in %s constructor "
"(unknown error code)", pattern, vcl_name);
}
else if (ret == PCRE2_ERROR_NOMEMORY) {
WS_Release(ctx->ws, strlen(buf) + 1);
VERR(ctx, "Cannot compile '%s' in %s constructor: %s"
"(truncated error message) at offset %zu", pattern,
vcl_name, err_offset);
}
else {
WS_Release(ctx->ws, ret);
VERR(ctx, "Cannot compile '%s' in %s constructor: %s "
"at offset %zu", pattern, vcl_name, buf,
err_offset);
}
WS_Reset(ctx->ws, buf);
PCRE2_COMPILE_CONTEXT_FREE(codesz, &ccontext);
return;
}
if (have_jit[codesz]) {
/* XXX check option compatibility; disable via param */
/* XXX set complete or soft/hard partial via param */
options |= PCRE2_JIT_COMPLETE;
ret = PCRE2_JIT_COMPILE(codesz, &code, options);
if (ret != 0) {
/* XXX DRY */
char *buf = WS_Snapshot(ctx->ws);
unsigned bytes = WS_Reserve(ctx->ws, 0);
ret = PCRE2_GET_ERROR_MESSAGE(codesz, ret, buf, bytes);
if (ret == PCRE2_ERROR_BADDATA) {
WS_ReleaseP(ctx->ws, buf);
VERR(ctx, "Cannot jit-compile '%s' in %s "
"constructor (unknown error code)",
pattern, vcl_name);
}
else if (ret == PCRE2_ERROR_NOMEMORY) {
WS_Release(ctx->ws, strlen(buf) + 1);
VERR(ctx, "Cannot jit-compile '%s' in %s "
"constructor: %s (truncated error message)",
pattern, vcl_name);
}
else {
WS_Release(ctx->ws, ret);
VERR(ctx, "Cannot jit-compile '%s' in %s "
"constructor: %s ", pattern, vcl_name,
buf);
}
WS_Reset(ctx->ws, buf);
PCRE2_COMPILE_CONTEXT_FREE(codesz, &ccontext);
return;
}
}
ALLOC_OBJ(regex, VMOD_PCRE2_REGEX_MAGIC);
AN(regex);
*regexp = regex;
regex->code = code;
regex->vcl_name = strdup(vcl_name);
AN(regex->vcl_name);
regex->codesz = codesz;
PCRE2_COMPILE_CONTEXT_FREE(codesz, &ccontext);
}
VCL_VOID
vmod_regex__fini(struct vmod_pcre2_regex **regexp)
{
struct vmod_pcre2_regex *regex;
if (regexp == NULL)
return;
regex = *regexp;
if (regex == NULL)
return;
CHECK_OBJ(regex, VMOD_PCRE2_REGEX_MAGIC);
if (regex->vcl_name != NULL)
free(regex->vcl_name);
PCRE2_CODE_FREE(regex->codesz, &regex->code);
FREE_OBJ(regex);
}
VCL_BOOL
vmod_regex_match(VRT_CTX, struct vmod_pcre2_regex *regex,
struct vmod_priv *gctx_task, VCL_STRING subject, VCL_INT len,
VCL_BOOL anchored, VCL_INT match_limit, VCL_INT offset_limit,
VCL_BOOL notbol, VCL_BOOL noteol, VCL_BOOL notempty,
VCL_BOOL notempty_atstart, VCL_BOOL no_jit,
VCL_BOOL no_utf_check, VCL_ENUM partials,
VCL_INT recursion_limit)
{
pcre2_general_context_t *gctx;
pcre2_match_context_t mctx;
pcre2_match_data_t *mdata;
struct vmod_priv *match_task = NULL;
uint32_t options = 0;
int ret;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(regex, VMOD_PCRE2_REGEX_MAGIC);
assert(have_lib[regex->codesz]);
AN(gctx_task);
if (subject == NULL) {
VERR(ctx, "subject is NULL in %s.match()", regex->vcl_name);
return 0;
}
/*
* The general context is task-scoped and shared by all objects
* from this VMOD in the task. It uses WS_Alloc as the custom
* allocator.
*/
if (gctx_task->priv == NULL) {
if ((gctx = WS_Alloc(ctx->ws, sizeof(*gctx))) == NULL) {
VERRNOMEM(ctx, "allocating general context in "
"%s.match()", regex->vcl_name);
return 0;
}
VSLb(ctx->vsl, SLT_Debug, "ws_malloc = %p, ws_free = %p",
ws_malloc, ws_free);
ret = PCRE2_GENERAL_CONTEXT_CREATE(gctx, ws_malloc, ws_free,
ctx->ws);
if (ret != 0) {
VERRNOMEM(ctx, "initializing general context in "
"%s.match()", regex->vcl_name);
return 0;
}
gctx_task->priv = gctx;
gctx_task->free = NULL;
}
else {
WS_Allocated(ctx->ws, gctx_task->priv,
sizeof(pcre2_general_context_t));
gctx = gctx_task->priv;
}
/* XXX PRIV_CALL scope for match context? */
VSLb(ctx->vsl, SLT_Debug,
"create mctx codesz = %d, mctx = %p, gctx = %p",
regex->codesz, &mctx, gctx);
ret = PCRE2_MATCH_CONTEXT_CREATE(regex->codesz, &mctx, gctx);
VSLb(ctx->vsl, SLT_Debug, "create mctx return = %d", ret);
if (ret != 0) {
VERRNOMEM(ctx, "creating match context in %s.match()",
regex->vcl_name);
return 0;
}
if (match_limit != 0) {
ret = PCRE2_SET_MATCH_LIMIT(regex->codesz, &mctx,
(uint32_t)match_limit);
AZ(ret);
}
if (offset_limit != 0) {
ret = PCRE2_SET_OFFSET_LIMIT(regex->codesz, &mctx,
(uint32_t)offset_limit);
AZ(ret);
}
if (recursion_limit != 0) {
ret = PCRE2_SET_RECURSION_LIMIT(regex->codesz, &mctx,
(uint32_t)recursion_limit);
AZ(ret);
}
/* The match data block is task-scoped for this object only. */
match_task = VRT_priv_task(ctx, regex);
AN(match_task);
if (match_task->priv == NULL) {
if ((mdata = WS_Alloc(ctx->ws, sizeof(*mdata))) == NULL) {
VERRNOMEM(ctx, "allocating match data in %s.match()",
regex->vcl_name);
return 0;
}
ret = PCRE2_MATCH_DATA_CREATE_FROM_PATTERN(regex->codesz, mdata,
&regex->code, gctx);
if (ret != 0) {
VERRNOMEM(ctx, "initializing match data in "
"%s.match()", regex->vcl_name);
return 0;
}
match_task->priv = mdata;
match_task->free = NULL;
}
else {
WS_Allocated(ctx->ws, match_task->priv,
sizeof(pcre2_match_context_t));
mdata = match_task->priv;
}
/* XXX PRIV_CALL scope for options? */
if (anchored != 0)
options |= PCRE2_ANCHORED;
if (notbol != 0)
options |= PCRE2_NOTBOL;
if (noteol != 0)
options |= PCRE2_NOTEOL;
if (notempty != 0)
options |= PCRE2_NOTEMPTY;
if (notempty_atstart != 0)
options |= PCRE2_NOTEMPTY_ATSTART;
if (no_jit != 0)
options |= PCRE2_NO_JIT;
if (no_utf_check != 0)
options |= PCRE2_NO_UTF_CHECK;
if (partials != NULL) {
VERR(ctx, "Partial matching not implemented yet in %s.match()",
regex->vcl_name);
return 0;
}
if (len == 0)
len = PCRE2_ZERO_TERMINATED;
else
len *= code_size[regex->codesz] / 8;
/* XXX param for start_offset */
/* XXX free the match context? */
ret = PCRE2_MATCH(regex->codesz, &regex->code, subject, (PCRE2_SIZE)len,
0, options, mdata, &mctx);
if (ret == PCRE2_ERROR_NOMATCH)
return 0;
assert(ret != PCRE2_ERROR_PARTIAL); /* XXX */
if (ret >= 0)
return 1;
/* XXX DRY */
char *buf = WS_Snapshot(ctx->ws);
unsigned bytes = WS_Reserve(ctx->ws, 0);
ret = PCRE2_GET_ERROR_MESSAGE(regex->codesz, ret, buf, bytes);
if (ret == PCRE2_ERROR_BADDATA) {
WS_ReleaseP(ctx->ws, buf);
VERR(ctx, "in %s.match() (unknown error code)",
regex->vcl_name);
}
else if (ret == PCRE2_ERROR_NOMEMORY) {
WS_Release(ctx->ws, strlen(buf) + 1);
VERR(ctx, "in %s.match(): %s (truncated error message)",
regex->vcl_name, buf);
}
else {
WS_Release(ctx->ws, ret);
VERR(ctx, "in %s.match(): %s ", regex->vcl_name, buf);
}
WS_Reset(ctx->ws, buf);
return 0;
}
/* Functions */
VCL_BOOL
vmod_config_bool(VRT_CTX, VCL_ENUM configs, VCL_ENUM libs)
{
uint32_t what, where;
int ret;
enum code_size lib;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
lib = decode_lib_enum(libs);
if (!have_lib[lib]) {
VERR(ctx, "%d-bit library not supported in pcre2.config_bool()",
code_size[lib]);
return 0;
}
if (strcmp(configs, "JIT") == 0)
what = PCRE2_CONFIG_JIT;
else if (strcmp(configs, "STACKRECURSE") == 0)
what = PCRE2_CONFIG_STACKRECURSE;
else if (strcmp(configs, "UNICODE") == 0)
what = PCRE2_CONFIG_UNICODE;
else
WRONG("Illegal config enum in config_bool");
ret = PCRE2_CONFIG(lib, what, &where);
assert(ret >= 0);
return (VCL_BOOL) where;
}
VCL_STRING
vmod_config_str(VRT_CTX, VCL_ENUM configs, VCL_ENUM libs)
{
uint32_t what;
int ret;
enum code_size lib;
void *buf;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
lib = decode_lib_enum(libs);
if (!have_lib[lib]) {
VERR(ctx, "%d-bit library not supported in pcre2.config_str()",
code_size[lib]);
return NULL;
}
if (strcmp(configs, "BSR") == 0)
what = PCRE2_CONFIG_BSR;
else if (strcmp(configs, "JITTARGET") == 0)
what = PCRE2_CONFIG_JITTARGET;
else if (strcmp(configs, "NEWLINE") == 0)
what = PCRE2_CONFIG_NEWLINE;
else if (strcmp(configs, "UNICODE_VERSION") == 0)
what = PCRE2_CONFIG_UNICODE_VERSION;
else if (strcmp(configs, "VERSION") == 0)
what = PCRE2_CONFIG_VERSION;
else
WRONG("Illegal config enum in config_str");
if (what == PCRE2_CONFIG_NEWLINE || what == PCRE2_CONFIG_BSR) {
uint32_t where;
ret = PCRE2_CONFIG(lib, what, &where);
assert(ret >= 0);
if (what == PCRE2_CONFIG_NEWLINE)
switch(where) {
case PCRE2_NEWLINE_CR:
return "CR";
case PCRE2_NEWLINE_LF:
return "LF";
case PCRE2_NEWLINE_CRLF:
return "CRLF";
case PCRE2_NEWLINE_ANY:
return "ANY";
case PCRE2_NEWLINE_ANYCRLF:
return "ANYCRLF";
default:
WRONG("Illegal result for "
"PCRE2_CONFIG_NEWLINE");
}
assert (what == PCRE2_CONFIG_BSR);
switch(where) {
case PCRE2_BSR_UNICODE:
return "UNICODE";
case PCRE2_BSR_ANYCRLF:
return "ANYCRLF";
default:
WRONG("Illegal result for PCRE2_CONFIG_BSR");
}
}
ret = PCRE2_CONFIG(lib, what, NULL);
if (what == PCRE2_CONFIG_JITTARGET && ret == PCRE2_ERROR_BADOPTION)
return "JIT not supported";
assert(ret > 0);
ret *= (code_size[lib] / 8);
if ((buf = WS_Alloc(ctx->ws, ret)) == NULL) {
ERRNOMEM(ctx, "allocating result in pcre2.config_str()");
return NULL;
}
ret = PCRE2_CONFIG(lib, what, buf);
assert(ret > 0);
return (VCL_STRING) buf;
}
VCL_INT
vmod_config_int(VRT_CTX, VCL_ENUM configs, VCL_ENUM libs)
{
uint32_t what, where;
int ret;
enum code_size lib;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
lib = decode_lib_enum(libs);
if (!have_lib[lib]) {
VERR(ctx, "%d-bit library not supported in pcre2.config_str()",
code_size[lib]);
return 0;
}
if (strcmp(configs, "LINKSIZE") == 0)
what = PCRE2_CONFIG_LINKSIZE;
else if (strcmp(configs, "MATCHLIMIT") == 0)
what = PCRE2_CONFIG_MATCHLIMIT;
else if (strcmp(configs, "PARENSLIMIT") == 0)
what = PCRE2_CONFIG_PARENSLIMIT;
else if (strcmp(configs, "RECURSIONLIMIT") == 0)
what = PCRE2_CONFIG_RECURSIONLIMIT;
else
WRONG("Illegal config enum in config_int");
ret = PCRE2_CONFIG(lib, what, &where);
assert(ret >= 0);
return (VCL_INT) where;
}
VCL_STRING
vmod_version(VRT_CTX __attribute__((unused)))
{
return VERSION;
}
#-
# This document is licensed under the same conditions
# as the libvmod-pcre2 project. See LICENSE for details.
#
# Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
#
$Module pcre2 3 access the pcre2 regular expression library
::
new OBJECT = ...
DESCRIPTION
===========
This Varnish Module (VMOD) provides access to the PCRE2 regular
expresion library.
$Object regex(STRING pattern, ENUM {LIB8, LIB16, LIB32} lib=0,
BOOL allow_empty_class=0, BOOL anchored=0,
ENUM {ANYCRLF, UNICODE} bsr=0, BOOL alt_bsux=0,
BOOL alt_circumflex=0, BOOL alt_verbnames=0, BOOL caseless=0,
BOOL dotall=0, BOOL dollar_endonly=0, BOOL dupnames=0,
BOOL extended=0, BOOL firstline=0, STRING locale=0,
BOOL match_unset_backref=0, INT max_pattern_len=0,
BOOL multiline=0, BOOL never_backslash_c=0, BOOL never_ucp=0,
BOOL never_utf=0, ENUM {CR, LF, CRLF, ANYCRLF, ANY} newline=0,
BOOL no_auto_capture=0, BOOL no_auto_possess=0,
BOOL no_dotstar_anchor=0, BOOL no_start_optimize=0,
BOOL no_utf_check=0, INT parens_nest_limit=0, BOOL ucp=0,
BOOL ungreedy=0, BOOL use_offset_limit=0, BOOL utf=0)
# XXX options for dfa_match, jit fast path, start_offset
$Method BOOL .match(PRIV_TASK, STRING, INT len=0, BOOL anchored=0,
INT match_limit=0, INT offset_limit=0, BOOL notbol=0,
BOOL noteol=0, BOOL notempty=0, BOOL notempty_atstart=0,
BOOL no_jit=0, BOOL no_utf_check = 0,
ENUM {HARD, SOFT} partial=0, INT recursion_limit=0)
$Function BOOL config_bool(ENUM {JIT, STACKRECURSE, UNICODE},
ENUM {LIB8, LIB16, LIB32} lib=0)
$Function STRING config_str(ENUM {BSR, JITTARGET, NEWLINE,
UNICODE_VERSION, VERSION},
ENUM {LIB8, LIB16, LIB32} lib=0)
$Function INT config_int(ENUM {LINKSIZE, MATCHLIMIT, PARENSLIMIT,
RECURSIONLIMIT}, ENUM {LIB8, LIB16, LIB32} lib=0)
$Function STRING version()
Returns the version string for this VMOD.
Example::
std.log("Using VMOD pcre2 version " + pcre2.version());
REQUIREMENTS
============
This VMOD requires Varnish ...
LIMITATIONS
===========
...
INSTALLATION
============
See `INSTALL.rst <INSTALL.rst>`_ in the source repository.
SEE ALSO
========
* varnishd(1)
* vcl(7)
* source repository: https://code.uplex.de/uplex-varnish/libvmod-pcre2
$Event event
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment