public inbox for buildroot@busybox.net
 help / color / mirror / Atom feed
From: Bernd Kuhls <bernd@kuhls.net>
To: buildroot@buildroot.org
Cc: David GOUARIN <dgouarin@gmail.com>,
	Fabrice Fontaine <fontaine.fabrice@gmail.com>,
	Laurent Cans <laurent.cans@gmail.com>,
	Mario Lang <mlang@blind.guru>,
	Maxim Kochetkov <fido_max@inbox.ru>,
	Phil Eichinger <phil.eichinger@gmail.com>
Subject: [Buildroot] [PATCH 05/20] package/c-icap: switch to pcre2
Date: Thu,  9 Apr 2026 10:42:49 +0200	[thread overview]
Message-ID: <20260409084305.3960494-5-bernd@kuhls.net> (raw)
In-Reply-To: <20260409084305.3960494-1-bernd@kuhls.net>

Added two patches backported from the upstream branch c_icap_0_6_x which
were backported by Debian to the 0.5.x branch.

Build-tested using this defconfig:

BR2_PACKAGE_PCRE2=y
BR2_PACKAGE_C_ICAP=y
BR2_PACKAGE_C_ICAP_MODULES=y

                             arm-aarch64 [ 1/32]: OK
                   bootlin-aarch64-glibc [ 2/32]: OK
               bootlin-aarch64-glibc-old [ 3/32]: FAILED
               bootlin-arcle-hs38-uclibc [ 4/32]: OK
                    bootlin-armv5-uclibc [ 5/32]: OK
                     bootlin-armv7-glibc [ 6/32]: OK
                   bootlin-armv7m-uclibc [ 7/32]: SKIPPED
                      bootlin-armv7-musl [ 8/32]: OK
                bootlin-m68k-5208-uclibc [ 9/32]: SKIPPED
               bootlin-m68k-68040-uclibc [10/32]: OK
             bootlin-microblazeel-uclibc [11/32]: OK
                  bootlin-mips64el-glibc [12/32]: OK
                bootlin-mipsel32r6-glibc [13/32]: OK
                   bootlin-mipsel-uclibc [14/32]: OK
                 bootlin-openrisc-uclibc [15/32]: OK
        bootlin-powerpc64le-power8-glibc [16/32]: OK
           bootlin-powerpc-e500mc-uclibc [17/32]: OK
                   bootlin-riscv32-glibc [18/32]: OK
                   bootlin-riscv64-glibc [19/32]: OK
                    bootlin-riscv64-musl [20/32]: OK
                 bootlin-s390x-z13-glibc [21/32]: OK
                      bootlin-sh4-uclibc [22/32]: OK
                   bootlin-sparc64-glibc [23/32]: OK
                    bootlin-sparc-uclibc [24/32]: OK
                    bootlin-x86-64-glibc [25/32]: OK
                     bootlin-x86-64-musl [26/32]: OK
                   bootlin-x86-64-uclibc [27/32]: OK
                   bootlin-x86-i686-musl [28/32]: OK
                   bootlin-xtensa-uclibc [29/32]: OK
                            br-arm-basic [30/32]: FAILED
                    br-arm-full-nothread [31/32]: SKIPPED
                      br-arm-full-static [32/32]: SKIPPED

32 builds, 4 skipped, 2 build failed, 0 legal-info failed, 0 show-info failed

The two build errors are unrelated to this patch, they are caused by
patch 0005-Fix-module-operation-prototypes-to-fix-GCC-15.x-buil.patch
which breaks the build with gcc <= 9.x:

http_auth.c: In function ‘basic_close’:
http_auth.c:412:25: error: parameter name omitted
 void basic_close(struct ci_server_conf *)

Signed-off-by: Bernd Kuhls <bernd@kuhls.net>
---
 .../c-icap/0006-Backport-pcre2-support.patch  | 569 ++++++++++++++++++
 ...ing-_CI_ASSERT-macro-for-pcre2-patch.patch |  50 ++
 package/c-icap/c-icap.mk                      |   9 +-
 3 files changed, 624 insertions(+), 4 deletions(-)
 create mode 100644 package/c-icap/0006-Backport-pcre2-support.patch
 create mode 100644 package/c-icap/0007-Add-missing-_CI_ASSERT-macro-for-pcre2-patch.patch

diff --git a/package/c-icap/0006-Backport-pcre2-support.patch b/package/c-icap/0006-Backport-pcre2-support.patch
new file mode 100644
index 0000000000..76d42f7527
--- /dev/null
+++ b/package/c-icap/0006-Backport-pcre2-support.patch
@@ -0,0 +1,569 @@
+From: Boyuan Yang <byang@debian.org>
+Date: Sat, 29 Jul 2023 19:13:16 -0400
+Subject: Backport pcre2 support
+
+Bug-Debian: https://bugs.debian.org/1000077
+Upstream: https://github.com/c-icap/c-icap-server/commit/888a98ff382d782729f000876b4e81f08d9046d3
+
+Downloaded from
+https://sources.debian.org/src/c-icap/1%3A0.5.10-7/debian/patches/0005-Backport-pcre2-support.patch
+
+[Bernd: rebased for 0.5.14]
+Signed-off-by: Bernd Kuhls <bernd@kuhls.net>
+---
+ Makefile.am        |  16 +++-
+ aserver.c          |   2 +
+ configure.ac       |  51 ++++++++++++-
+ include/ci_regex.h |  43 ++++++++++-
+ regex.c            | 210 ++++++++++++++++++++++++++++++++++++++++++++++++-----
+ types_ops.c        |   4 +-
+ 6 files changed, 296 insertions(+), 30 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index acfa0d0..ebdf51c 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -22,11 +22,23 @@ bin_PROGRAMS = c-icap
+ 
+ bin_SCRIPTS = c-icap-config c-icap-libicapapi-config
+ 
++UTIL_FLAGS=
++UTIL_LDADD=
+ UTIL_LIB_SOURCES=net_io.c util.c os/unix/net_io.c os/unix/proc_mutex.c os/unix/shared_mem.c os/unix/threads.c os/unix/utilfunc.c os/unix/dlib.c
+ if USE_OPENSSL
+ UTIL_LIB_SOURCES += openssl/net_io_ssl.c
+ endif
++
+ if USE_REGEX
++if USE_PCRE2
++UTIL_FLAGS += @PCRE2_ADD_FLAG@
++UTIL_LDADD += @PCRE2_ADD_LDADD@
++endif
++if USE_PCRE
++UTIL_FLAGS += @PCRE_ADD_FLAG@
++UTIL_LDADD += @PCRE_ADD_LDADD@
++endif
++
+ UTIL_LIB_SOURCES += regex.c
+ endif
+ UTIL_SOURCES=os/unix/proc_utils.c
+@@ -50,9 +62,9 @@ c_icap_SOURCES = aserver.c request.c cfg_param.c \
+ 
+ 
+ # libicapapi ......
+-libicapapi_la_CFLAGS= $(INVISIBILITY_CFLAG) -I$(srcdir)/include/ -Iinclude/ @ZLIB_ADD_FLAG@ @OPENSSL_ADD_FLAG@ @BZLIB_ADD_FLAG@ @BROTLI_ADD_FLAG@ @ZSTD_ADD_FLAG@ @PCRE_ADD_FLAG@ -DCI_BUILD_LIB
++libicapapi_la_CFLAGS= $(INVISIBILITY_CFLAG) -I$(srcdir)/include/ -Iinclude/ @ZLIB_ADD_FLAG@ @OPENSSL_ADD_FLAG@ @BZLIB_ADD_FLAG@ @BROTLI_ADD_FLAG@ @ZSTD_ADD_FLAG@ $(UTIL_FLAG) -DCI_BUILD_LIB
+ 
+-libicapapi_la_LIBADD = @ZLIB_ADD_LDADD@ @BZLIB_ADD_LDADD@ @BROTLI_ADD_LDADD@ @ZSTD_ADD_LDADD@ @PCRE_ADD_LDADD@ @DL_ADD_FLAG@ @THREADS_LDADD@ @OPENSSL_ADD_LDADD@
++libicapapi_la_LIBADD = @ZLIB_ADD_LDADD@ @BZLIB_ADD_LDADD@ @BROTLI_ADD_LDADD@ @ZSTD_ADD_LDADD@ $(UTIL_LDADD) @DL_ADD_FLAG@ @THREADS_LDADD@ @OPENSSL_ADD_LDADD@
+ libicapapi_la_LDFLAGS= -shared -version-info @CICAPLIB_VERSION@ @LIBS_LDFLAGS@ @THREADS_LDFLAGS@
+ 
+ export EXT_PROGRAMS_MKLIB = @ZLIB_LNDIR_LDADD@ @BZLIB_LNDIR_LDADD@ @BROTLI_LNDIR_LDADD@ @ZSTD_LNDIR_LDADD@ @PCRE_LNDIR_LDADD@ @OPENSSL_LNDIR_LDADD@
+diff --git a/aserver.c b/aserver.c
+index 9eaa609..990be9d 100644
+--- a/aserver.c
++++ b/aserver.c
+@@ -29,6 +29,7 @@
+ #endif
+ #include "txtTemplate.h"
+ #include "commands.h"
++#include "ci_regex.h"
+ 
+ /*
+ extern char *PIDFILE;
+@@ -142,6 +143,7 @@ int main(int argc, char **argv)
+     }
+     ci_txt_template_init();
+     ci_txt_template_set_dir(DATADIR"templates");
++    ci_regex_memory_init();
+     commands_init();
+ 
+     if (!(CI_CONF.MAGIC_DB = ci_magic_db_load(CI_CONF.magics_file))) {
+diff --git a/configure.ac b/configure.ac
+index 2144011..08a937f 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -246,6 +246,7 @@ AC_ARG_ENABLE(rpath,
+ #Routines used for checking libraries
+ AC_DEFUN([ICFG_STATE_SAVE],[
+ #save state
++ICFG_OLD_CPPFLAGS=$CPPFLAGS
+ ICFG_OLD_CFLAGS=$CFLAGS
+ ICFG_OLD_LDFLAGS=$LDFLAGS
+ ICFG_OLD_LIBS=$LIBS
+@@ -253,7 +254,8 @@ ICFG_OLD_LIBS=$LIBS
+ 
+ #Routines used for checking libraries
+ AC_DEFUN([ICFG_STATE_ROLLBACK],[
+-#save state
++#rollback saved state
++CPPFLAGS=$ICFG_OLD_CPPFLAGS
+ CFLAGS=$ICFG_OLD_CFLAGS
+ LDFLAGS=$ICFG_OLD_LDFLAGS
+ LIBS=$ICFG_OLD_LIBS
+@@ -650,6 +652,45 @@ if test a"$libmemcached" != "ano"; then
+     ICFG_STATE_ROLLBACK
+ fi
+ 
++# Check for PCRE2 regex library
++AC_ARG_WITH(pcre2,
++[       --with-pcre2     Path to PCRE2 library],
++[
++case "$withval" in
++     yes)
++        pcre2=yes;
++     ;;
++     no)
++        pcre2=no;
++     ;;
++     *)
++        pcre2=yes;
++        pcre2path=$withval;
++     ;;
++     esac
++],
++[ pcre2=yes]
++)
++
++if test a"$pcre2" != "ano"; then
++   ICFG_STATE_SAVE(PCRE2)
++   CPPFLAGS="$CPPFLAGS -DPCRE2_CODE_UNIT_WIDTH=8"
++   if test "a$pcre2path" != "a"; then
++       CFLAGS="$CFLAGS -I$pcre2path/include"
++       LDFLAGS="$LDFLAGS -L$pcre2path/lib"
++   fi
++   AC_CHECK_HEADERS(pcre2.h,
++                    AC_CHECK_LIB(pcre2-8, pcre2_match_8,[pcre2=yes],[pcre2=no]),
++                    [pcre2=no]
++   )
++
++   if test "a$pcre2" = "ayes"; then
++       AC_DEFINE(HAVE_PCRE2,1,[Define HAVE_PCRE2 if pcre2 installed])
++       ICFG_BUILD_FLAGS(PCRE2, "$pcre2path", "-lpcre2-8")
++   fi
++   ICFG_STATE_ROLLBACK
++fi
++
+ # Check for PCRE regex library
+ AC_ARG_WITH(pcre,
+ [       --with-pcre     Path to PCRE library],
+@@ -670,7 +711,7 @@ case "$withval" in
+ [ pcre=yes]
+ )
+ 
+-if test a"$pcre" != "ano"; then
++if test a"$pcre" != "ano" -a a"$pcre2" != "ayes"; then
+    ICFG_STATE_SAVE(PCRE)
+    if test "a$pcrepath" != "a"; then
+        CFLAGS="$CFLAGS -I$pcrepath/include"
+@@ -714,7 +755,7 @@ AC_CHECK_HEADERS(regex.h,
+   )
+ 
+ USE_REGEX=0
+-if test "a$pcre" = "ayes" -o "a$posix_regex" = "ayes"; then
++if test "a$pcre2" = "ayes" -o "a$pcre" = "ayes" -o "a$posix_regex" = "ayes"; then
+    USE_REGEX=1
+ fi
+ AC_SUBST(USE_REGEX)
+@@ -1001,7 +1042,9 @@ AM_CONDITIONAL(ISCYGWIN,[test a"$iscygwin" != a])
+ # Now determine which modules will going to build .....
+ 
+ AM_CONDITIONAL(USE_OPENSSL, [test a"$openssl" != "ano"])
+-AM_CONDITIONAL(USE_REGEX, [test a"$pcre" = "ayes" -o a"$posix_regex" = "ayes"])
++AM_CONDITIONAL(USE_PCRE2, [test a"$pcre2" = "ayes"])
++AM_CONDITIONAL(USE_PCRE, [test a"$pcre" = "ayes"])
++AM_CONDITIONAL(USE_REGEX, [test a"$pcre2" = "ayes" -o a"$pcre" = "ayes" -o a"$posix_regex" = "ayes"])
+ AM_CONDITIONAL(USEPERL,[test a"$perlcore" != a])
+ AM_CONDITIONAL(USEBDB,   [test a"$libdb" != ano])
+ AM_CONDITIONAL(USELDAP, [test a"$libldap" != ano])
+diff --git a/include/ci_regex.h b/include/ci_regex.h
+index 27afc9c..df7b77a 100644
+--- a/include/ci_regex.h
++++ b/include/ci_regex.h
+@@ -33,18 +33,57 @@ struct ci_regex_match {
+     size_t s;
+     size_t e;
+ };
+-typedef struct ci_regex_match ci_regex_matches_t[10];
++#define CI_REGEX_SUBMATCHES 10
++typedef struct ci_regex_match ci_regex_matches_t[CI_REGEX_SUBMATCHES];
+ typedef struct ci_regex_replace_part {
+     const void *user_data;
+     ci_regex_matches_t matches;
+ } ci_regex_replace_part_t;
+ 
+-#define ci_regex_create_match_list() ci_list_create(32768, sizeof(ci_regex_replace_part_t))
++/**
++ \brief Builds a regex match list to store regex matches.
++ * The regex match list is a ci_list_t object which stores ci_regex_replace_part
++ * objects as items.
++ \ingroup UTILITY
++ */
++#define ci_regex_create_match_list() ci_list_create(1024, sizeof(ci_regex_replace_part_t))
++
++/**
++  \brief Parses a regex expresion having the form /regex/flags
++  \ingroup UTILITY
++  *
++ */
+ CI_DECLARE_FUNC(char *) ci_regex_parse(const char *str, int *flags, int *recursive);
++
++/**
++  \brief Compiles a regex expresion into an internal form.
++  \param regex_str The regex string normally returned by ci_regex_parse function
++  \param regex_flags The regex flags built using the ci_regex_parse
++  \ingroup UTILITY
++ */
+ CI_DECLARE_FUNC(ci_regex_t) ci_regex_build(const char *regex_str, int regex_flags);
++
++/**
++ * Releases objects built using the ci_regex_build
++ \ingroup UTILITY
++ */
+ CI_DECLARE_FUNC(void) ci_regex_free(ci_regex_t regex);
++
++/**
++ * Matchs a compiled regex expresion of type ci_regex_t  against the given string.
++ \param regex The compiled regex expresion
++ \param str The string to match against
++ \param len The str string length. For '\0' terminated strings set it to -1
++ \param recurs If it is not NULL matches recursivelly
++ \param matches The regex match list to store matches. It can be NULL
++ \param user_data pointer to user data to store with matches in rege match list.
++ \ingroup UTILITY
++ */
+ CI_DECLARE_FUNC(int) ci_regex_apply(const ci_regex_t regex, const char *str, int len, int recurs, ci_list_t *matches, const void *user_data);
+ 
++
++CI_DECLARE_FUNC(void) ci_regex_memory_init();
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff --git a/regex.c b/regex.c
+index 82277df..de9b387 100644
+--- a/regex.c
++++ b/regex.c
+@@ -1,14 +1,107 @@
+ #include "common.h"
+ #include "debug.h"
+ #include "array.h"
++#include "mem.h"
+ #include "ci_regex.h"
+ 
+-#ifdef HAVE_PCRE
++#if defined(HAVE_PCRE2)
++#define PCRE2_CODE_UNIT_WIDTH 8 // TODO: make it configurable via configure
++#include <pcre2.h>
++#elif defined(HAVE_PCRE)
+ #include <pcre.h>
+ #else
+ #include <regex.h>
+ #endif
+ 
++#if defined(HAVE_PCRE2)
++pcre2_general_context *pcre2GenContext = NULL;
++pcre2_match_context *pcre2MatchContext = NULL;
++
++void *pcre2_malloc(PCRE2_SIZE size, void *udata)
++{
++    void *p = ci_buffer_alloc(size);
++    return p;
++}
++
++void pcre2_free(void *p, void *udata)
++{
++    ci_buffer_free(p);
++}
++
++struct {
++    char *name;
++    uint32_t flag;
++} pcre2_flags[] = {
++    {"ANCHORED", 0x80000000u},
++    {"NO_UTF_CHECK", 0x40000000u},
++    {"ENDANCHORED", 0x20000000u},
++    {"ALLOW_EMPTY_CLASS", 0x00000001u},
++    {"ALT_BSUX", 0x00000002u},
++    {"AUTO_CALLOUT", 0x00000004u},
++    {"CASELESS", 0x00000008u},
++    {"DOLLAR_ENDONLY", 0x00000010u},
++    {"DOTALL", 0x00000020u},
++    {"DUPNAMES", 0x00000040u},
++    {"EXTENDED", 0x00000080u},
++    {"FIRSTLINE", 0x00000100u},
++    {"MATCH_UNSET_BACKREF", 0x00000200u},
++    {"MULTILINE", 0x00000400u},
++    {"NEVER_UCP", 0x00000800u},
++    {"NEVER_UTF", 0x00001000u},
++    {"NO_AUTO_CAPTURE", 0x00002000u},
++    {"NO_AUTO_POSSESS", 0x00004000u},
++    {"NO_DOTSTAR_ANCHOR", 0x00008000u},
++    {"NO_START_OPTIMIZE", 0x00010000u},
++    {"UCP", 0x00020000u},
++    {"UNGREEDY", 0x00040000u},
++    {"UTF", 0x00080000u},
++    {"NEVER_BACKSLASH_C", 0x00100000u},
++    {"ALT_CIRCUMFLEX", 0x00200000u},
++    {"ALT_VERBNAMES", 0x00400000u},
++    {"USE_OFFSET_LIMIT", 0x00800000u},
++    {"EXTENDED_MORE", 0x01000000u},
++    {"LITERAL", 0x02000000u},
++    {"MATCH_INVALID_UTF", 0x04000000u},
++    {NULL, 0}
++};
++
++int pcre2_flag_parse(const char **f)
++{
++    const char *s = (*f);
++    if (*s != '<')
++        return 0;
++    s++;
++    const char *e = strchr(s, '>');
++    if (e)
++        *f = e;
++    else {
++        e = s + strlen(s);
++        *f = e - 1;
++    }
++    size_t len = e - s;
++    e--;
++    if (!len)
++        return 0;
++
++    int i;
++    for (i = 0; pcre2_flags[i].name != NULL; i++) {
++        if (strncmp(pcre2_flags[i].name, s, len) == 0)
++            return pcre2_flags[i].flag;
++    }
++    return 0;
++}
++
++#endif
++
++void ci_regex_memory_init()
++{
++#if defined(HAVE_PCRE2)
++    pcre2GenContext = pcre2_general_context_create(pcre2_malloc, pcre2_free,  NULL);
++    pcre2MatchContext = pcre2_match_context_create(pcre2GenContext);
++#endif
++}
++
++
+ 
+ char *ci_regex_parse(const char *str, int *flags, int *recursive)
+ {
+@@ -29,7 +122,10 @@ char *ci_regex_parse(const char *str, int *flags, int *recursive)
+     s[slen] = '\0';
+ 
+     *flags = 0;
+-#ifdef HAVE_PCRE
++#if defined(HAVE_PCRE2)
++    *flags |= PCRE2_NEWLINE_ANY;
++    *flags |= PCRE2_NEWLINE_ANYCRLF;
++#elif defined(HAVE_PCRE)
+     *flags |= PCRE_NEWLINE_ANY;
+     *flags |= PCRE_NEWLINE_ANYCRLF;
+ #else
+@@ -38,7 +134,27 @@ char *ci_regex_parse(const char *str, int *flags, int *recursive)
+ #endif
+ 
+     while (*e != '\0') {
+-#ifdef HAVE_PCRE
++#if defined(HAVE_PCRE2)
++        if (*e == 'i')
++            *flags = *flags | PCRE2_CASELESS;
++        else if (*e == 'm')
++            *flags |= PCRE2_MULTILINE;
++        else if (*e == 's')
++            *flags |= PCRE2_DOTALL;
++        else if (*e == 'x')
++            *flags |= PCRE2_EXTENDED;
++        else if (*e == 'A')
++            *flags |= PCRE2_ANCHORED;
++        else if (*e == 'D')
++            *flags |= PCRE2_DOLLAR_ENDONLY;
++        else if (*e == 'U')
++            *flags |= PCRE2_UNGREEDY;
++        else if (*e == 'u')
++            *flags |= PCRE2_UTF | PCRE2_UCP;
++        else if (*e == '<') {
++            *flags |= pcre2_flag_parse(&e);
++        }
++#elif defined(HAVE_PCRE)
+         if (*e == 'i')
+             *flags = *flags | PCRE_CASELESS;
+         else if (*e == 'm')
+@@ -74,7 +190,19 @@ char *ci_regex_parse(const char *str, int *flags, int *recursive)
+ 
+ ci_regex_t ci_regex_build(const char *regex_str, int regex_flags)
+ {
+-#ifdef HAVE_PCRE
++#if defined(HAVE_PCRE2)
++    pcre2_code *re;
++    int errcode;
++    PCRE2_SIZE erroffset;
++    re =  pcre2_compile((PCRE2_SPTR)regex_str, PCRE2_ZERO_TERMINATED, (uint32_t)regex_flags, &errcode, &erroffset, NULL);
++    if (re == NULL) {
++        PCRE2_UCHAR errbuf[256];
++        pcre2_get_error_message(errcode, errbuf, sizeof(errbuf));
++        ci_debug_printf(2, "PCRE2 compilation of '%s' failed at offset %d: %s\n", regex_str, (int)erroffset, errbuf);
++        return NULL;
++    }
++    return (ci_regex_t)re;
++#elif defined(HAVE_PCRE)
+     pcre *re;
+     const char *error;
+     int erroffset;
+@@ -103,7 +231,9 @@ ci_regex_t ci_regex_build(const char *regex_str, int regex_flags)
+ 
+ void ci_regex_free(ci_regex_t regex)
+ {
+-#ifdef HAVE_PCRE
++#if defined(HAVE_PCRE2)
++    pcre2_code_free((pcre2_code *)regex);
++#elif defined(HAVE_PCRE)
+     pcre_free((pcre *)regex);
+ #else
+     regfree((regex_t *)regex);
+@@ -112,7 +242,7 @@ void ci_regex_free(ci_regex_t regex)
+ }
+ 
+ #ifdef HAVE_PCRE
+-#define OVECCOUNT 30    /* should be a multiple of 3 */
++#define OVECCOUNT (3*CI_REGEX_SUBMATCHES)    /* should be a multiple of 3 */
+ #endif
+ 
+ int ci_regex_apply(const ci_regex_t regex, const char *str, int len, int recurs, ci_list_t *matches, const void *user_data)
+@@ -120,14 +250,42 @@ int ci_regex_apply(const ci_regex_t regex, const char *str, int len, int recurs,
+     int count = 0, i;
+     ci_regex_replace_part_t parts;
+ 
+-    if (!str)
++    if (!str || len == 0)
+         return 0;
+ 
+-#ifdef HAVE_PCRE
++#if defined(HAVE_PCRE2)
++    PCRE2_SIZE offset = 0;
++    pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(regex, pcre2GenContext);
++    do {
++        int str_length = len > 0 ? len : PCRE2_ZERO_TERMINATED;
++        int rcaptures = pcre2_match(regex, (PCRE2_SPTR)str, str_length, offset, 0, match_data, pcre2MatchContext);
++        if (rcaptures >= 0)
++            count++;
++        if (rcaptures > 0 && matches) {
++            PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
++            for (i = 0; i < rcaptures && i < CI_REGEX_SUBMATCHES; i++) {
++                _CI_ASSERT(ovector[2*i+1] >= ovector[2*i]);
++                if (matches) {
++                    parts.user_data = user_data;
++                    memset(parts.matches, 0, sizeof(ci_regex_matches_t));
++                    ci_debug_printf(9, "\t sub-match pattern (pos:%d-%d): '%.*s'\n", (int)ovector[2*i], (int)ovector[2*i+1], (int)(ovector[2*i + 1] - ovector[2*i]), str+ovector[2*i]);
++                    parts.matches[i].s = ovector[2*i];
++                    parts.matches[i].e = ovector[2*i+1];
++                }
++                ci_list_push_back(matches, (void *)&parts);
++            }
++            offset = ovector[1]; /*Assert that it is less than strlen(str)?*/
++        } else if (rcaptures < 0) {
++            /* maybe check and report the exact error?*/
++            offset = 0;
++        } /* the rcaptures==0 not possible for our case, but maybe check and warn?*/
++    } while (recurs && offset > 0);
++    pcre2_match_data_free(match_data);
++#elif defined(HAVE_PCRE)
+     int ovector[OVECCOUNT];
+     int rc;
+     int offset = 0;
+-    int str_length = len >=0 ? len : strlen(str);
++    int str_length = len > 0 ? len : strlen(str);
+     do {
+         memset(ovector, 0, sizeof(ovector));
+         rc = pcre_exec(regex, NULL, str, str_length, offset, 0, ovector, OVECCOUNT);
+@@ -139,7 +297,7 @@ int ci_regex_apply(const ci_regex_t regex, const char *str, int len, int recurs,
+             if (matches) {
+                 parts.user_data = user_data;
+                 memset(parts.matches, 0, sizeof(ci_regex_matches_t));
+-                for (i = 0; i < 10 && ovector[2*i+1] > ovector[2*i]; ++i) {
++                for (i = 0; i < CI_REGEX_SUBMATCHES && ovector[2*i+1] > ovector[2*i]; ++i) {
+                     ci_debug_printf(9, "\t sub-match pattern (pos:%d-%d): '%.*s'\n", ovector[2*i], ovector[2*i+1], ovector[2*i + 1] - ovector[2*i], str+ovector[2*i]);
+                     parts.matches[i].s = ovector[2*i];
+                     parts.matches[i].e = ovector[2*i+1];
+@@ -151,17 +309,27 @@ int ci_regex_apply(const ci_regex_t regex, const char *str, int len, int recurs,
+ 
+ #else
+     int retcode;
+-    regmatch_t pmatch[10];
++    regmatch_t pmatch[CI_REGEX_SUBMATCHES];
++    char *tmpS = NULL;
++    const char *s;
++    if (len > 0 && len < strlen(str)) {
++        tmpS = ci_buffer_alloc(len + 1);
++        _CI_ASSERT(tmpS);
++        memcpy(tmpS, str, len);
++        tmpS[len] = '\0';
++        s = tmpS;
++    } else
++        s = str;
+     do {
+-        if ((retcode = regexec(regex, str, 10, pmatch, 0)) == 0) {
++        if ((retcode = regexec(regex, s, CI_REGEX_SUBMATCHES, pmatch, 0)) == 0) {
+             ++count;
+-            ci_debug_printf(9, "Match pattern (pos:%d-%d): '%.*s'\n", pmatch[0].rm_so, pmatch[0].rm_eo, pmatch[0].rm_eo - pmatch[0].rm_so, str+pmatch[0].rm_so);
++            ci_debug_printf(9, "Match pattern (pos:%d-%d): '%.*s'\n", pmatch[0].rm_so, pmatch[0].rm_eo, pmatch[0].rm_eo - pmatch[0].rm_so, s+pmatch[0].rm_so);
+ 
+             if (matches) {
+                 parts.user_data = user_data;
+                 memset(parts.matches, 0, sizeof(ci_regex_matches_t));
+-                for (i = 0; i < 10 && pmatch[i].rm_eo > pmatch[i].rm_so; ++i) {
+-                    ci_debug_printf(9, "\t sub-match pattern (pos:%d-%d): '%.*s'\n", pmatch[i].rm_so, pmatch[i].rm_eo, pmatch[i].rm_eo - pmatch[i].rm_so, str+pmatch[i].rm_so);
++                for (i = 0; i < CI_REGEX_SUBMATCHES && pmatch[i].rm_eo > pmatch[i].rm_so; ++i) {
++                    ci_debug_printf(9, "\t sub-match pattern (pos:%d-%d): '%.*s'\n", pmatch[i].rm_so, pmatch[i].rm_eo, pmatch[i].rm_eo - pmatch[i].rm_so, s+pmatch[i].rm_so);
+                     parts.matches[i].s = pmatch[i].rm_so;
+                     parts.matches[i].e = pmatch[i].rm_eo;
+                 }
+@@ -169,14 +337,16 @@ int ci_regex_apply(const ci_regex_t regex, const char *str, int len, int recurs,
+             }
+ 
+             if (pmatch[0].rm_so >= 0 && pmatch[0].rm_eo >= 0 && pmatch[0].rm_so != pmatch[0].rm_eo) {
+-                str += pmatch[0].rm_eo;
+-                ci_debug_printf(8, "I will check again starting from: %s\n", str);
++                s += pmatch[0].rm_eo;
++                ci_debug_printf(8, "I will check again starting from: %s\n", s);
+             } else /*stop here*/
+-                str = NULL;
++                s = NULL;
+         }
+-    } while (recurs && str && *str != '\0' && retcode == 0);
++    } while (recurs && s && *s != '\0' && retcode == 0);
++    if (tmpS)
++        ci_buffer_free(tmpS);
+ #endif
+ 
+-    ci_debug_printf(5, "ci_regex_apply matches count: %d\n", count);
++    ci_debug_printf(5, "ci_regex_apply string '%s' matches count: %d\n", str, count);
+     return count;
+ }
+diff --git a/types_ops.c b/types_ops.c
+index 78798c6..1310d4b 100644
+--- a/types_ops.c
++++ b/types_ops.c
+@@ -273,7 +273,7 @@ int regex_cmp(const void *key1, const void *key2)
+     struct ci_acl_regex *reg = (struct ci_acl_regex *)key1;
+     if (!key2)
+         return -1;
+-    return (ci_regex_apply(reg->preg, (const char *)key2, strlen(key2), 0, NULL, NULL) == 0 ? 1 : 0);
++    return (ci_regex_apply(reg->preg, (const char *)key2, -1, 0, NULL, NULL) == 0 ? 1 : 0);
+ }
+ 
+ int regex_equal(const void *key1, const void *key2)
+@@ -281,7 +281,7 @@ int regex_equal(const void *key1, const void *key2)
+     struct ci_acl_regex *reg = (struct ci_acl_regex *)key1;
+     if (!key2)
+         return 0;
+-    return ci_regex_apply(reg->preg, (const char *)key2, strlen(key2), 0, NULL, NULL) != 0;
++    return ci_regex_apply(reg->preg, (const char *)key2, -1, 0, NULL, NULL) != 0;
+ }
+ 
+ size_t regex_len(const void *key)
diff --git a/package/c-icap/0007-Add-missing-_CI_ASSERT-macro-for-pcre2-patch.patch b/package/c-icap/0007-Add-missing-_CI_ASSERT-macro-for-pcre2-patch.patch
new file mode 100644
index 0000000000..0209722a16
--- /dev/null
+++ b/package/c-icap/0007-Add-missing-_CI_ASSERT-macro-for-pcre2-patch.patch
@@ -0,0 +1,50 @@
+From: Boyuan Yang <byang@debian.org>
+Date: Sat, 29 Jul 2023 19:34:51 -0400
+Subject: Add missing _CI_ASSERT macro for pcre2 patch
+
+Upstream: https://github.com/c-icap/c-icap-server/commit/9d4b75b2a044669cbe4570f95f0f8f00f09b0d21
+
+Downloaded from
+https://sources.debian.org/src/c-icap/1%3A0.5.10-7/debian/patches/0007-Add-missing-_CI_ASSERT-macro-for-pcre2-patch.patch
+
+Signed-off-by: Bernd Kuhls <bernd@kuhls.net>
+---
+ debug.c         | 10 ++++++++++
+ include/debug.h |  3 +++
+ 2 files changed, 13 insertions(+)
+
+diff --git a/debug.c b/debug.c
+index 8a3bf6d..4f34a87 100644
+--- a/debug.c
++++ b/debug.c
+@@ -47,6 +47,16 @@ void __ldebug_printf(int i, const char *format, ...)
+ }
+ #endif
+ 
++void ci_debug_abort(const char *file, int line, const char *function, const char *mesg)
++{
++    ci_debug_printf(1, "Abort at %s, %d, %s: \'%s\'\n", file, line, function, mesg);
++    fflush(stderr);
++    fflush(stdout);
++    abort();
++}
++
++void (*__ci_debug_abort)(const char *file, int line, const char *function, const char *mesg) = ci_debug_abort;
++
+ /*
+ void debug_print_request(ci_request_t *req){
+      int i,j;
+diff --git a/include/debug.h b/include/debug.h
+index 9373ec9..990cce7 100644
+--- a/include/debug.h
++++ b/include/debug.h
+@@ -44,6 +44,9 @@ CI_DECLARE_DATA extern void (*__log_error)(void *req, const char *format,... );
+ #define ci_debug_printf(i, args...) if(i<=CI_DEBUG_LEVEL){ if(__log_error) (*__log_error)(NULL,args); if(CI_DEBUG_STDOUT) printf(args);}
+ #endif
+ 
++CI_DECLARE_DATA extern void (*__ci_debug_abort)(const char *file, int line, const char *function, const char *mesg);
++#define _CI_ASSERT(expression) {if (!(expression)) (*__ci_debug_abort)(__FILE__, __LINE__, __func__, #expression);}
++
+ #ifdef __cplusplus
+ }
+ #endif
diff --git a/package/c-icap/c-icap.mk b/package/c-icap/c-icap.mk
index 7e1b73cd2e..ee351d9781 100644
--- a/package/c-icap/c-icap.mk
+++ b/package/c-icap/c-icap.mk
@@ -13,6 +13,7 @@ C_ICAP_CPE_ID_VALID = YES
 C_ICAP_INSTALL_STAGING = YES
 C_ICAP_CONFIG_SCRIPTS = c-icap-config c-icap-libicapapi-config
 C_ICAP_CONF_OPTS = \
+	--without-pcre \
 	--without-perl \
 	--without-zstd \
 	--enable-large-files \
@@ -63,11 +64,11 @@ else
 C_ICAP_CONF_OPTS += --without-openssl
 endif
 
-ifeq ($(BR2_PACKAGE_PCRE),y)
-C_ICAP_CONF_OPTS += --with-pcre
-C_ICAP_DEPENDENCIES += pcre
+ifeq ($(BR2_PACKAGE_PCRE2),y)
+C_ICAP_CONF_OPTS += --with-pcre2
+C_ICAP_DEPENDENCIES += pcre2
 else
-C_ICAP_CONF_OPTS += --without-pcre
+C_ICAP_CONF_OPTS += --without-pcre2
 endif
 
 ifeq ($(BR2_PACKAGE_ZLIB),y)
-- 
2.47.3

_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot

  parent reply	other threads:[~2026-04-09  8:44 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-09  8:42 [Buildroot] [PATCH 01/20] package/shadowsocks-libev: bump version to 3.3.6 Bernd Kuhls
2026-04-09  8:42 ` [Buildroot] [PATCH 02/20] package/c-icap: fix musl build Bernd Kuhls
2026-04-09  8:42 ` [Buildroot] [PATCH 03/20] package/c-icap: bump version to 0.5.14 Bernd Kuhls
2026-04-09  8:42 ` [Buildroot] [PATCH 04/20] package/c-icap-modules: bump version to 0.5.7 Bernd Kuhls
2026-04-09  8:42 ` Bernd Kuhls [this message]
2026-04-09  8:42 ` [Buildroot] [PATCH 06/20] package/brltty: remove optional support for pcre, keep pcre2 Bernd Kuhls
2026-04-09  8:42 ` [Buildroot] [PATCH 07/20] package/haproxy: " Bernd Kuhls
2026-04-09  8:42 ` [Buildroot] [PATCH 08/20] package/kismet: " Bernd Kuhls
2026-04-09  8:42 ` [Buildroot] [PATCH 09/20] package/pound: " Bernd Kuhls
2026-04-09  8:42 ` [Buildroot] [PATCH 10/20] package/sngrep: " Bernd Kuhls
2026-04-09  8:42 ` [Buildroot] [PATCH 11/20] package/tvheadend: " Bernd Kuhls
2026-04-09  8:42 ` [Buildroot] [PATCH 12/20] package/wget: " Bernd Kuhls
2026-04-09  8:42 ` [Buildroot] [PATCH 13/20] package/aircrack-ng: switch to pcre2 Bernd Kuhls
2026-04-09  8:42 ` [Buildroot] [PATCH 14/20] package/freeradius-server: " Bernd Kuhls
2026-04-09  8:42 ` [Buildroot] [PATCH 15/20] package/freeswitch: " Bernd Kuhls
2026-04-09  8:43 ` [Buildroot] [PATCH 16/20] package/kodi: " Bernd Kuhls
2026-04-09  8:43 ` [Buildroot] [PATCH 17/20] package/postgis: " Bernd Kuhls
2026-04-09  8:43 ` [Buildroot] [PATCH 18/20] package/slang: disable pcre module Bernd Kuhls
2026-04-09  8:43 ` [Buildroot] [PATCH 19/20] package/zsh: switch to pcre2 Bernd Kuhls
2026-04-09  8:43 ` [Buildroot] [PATCH 20/20] package/pcre: remove package Bernd Kuhls

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260409084305.3960494-5-bernd@kuhls.net \
    --to=bernd@kuhls.net \
    --cc=buildroot@buildroot.org \
    --cc=dgouarin@gmail.com \
    --cc=fido_max@inbox.ru \
    --cc=fontaine.fabrice@gmail.com \
    --cc=laurent.cans@gmail.com \
    --cc=mlang@blind.guru \
    --cc=phil.eichinger@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox