From: Victor Seva Date: Wed, 9 Aug 2023 10:48:41 +0000 (+0000) Subject: regex: migration to pcre2 X-Git-Tag: archive/raspbian/5.7.2-1+rpi1^2~1 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=06c0d77d44e4ba41ba2ee9d3c2eb5659e4d53975;p=kamailio.git regex: migration to pcre2 Gbp-Pq: Topic upstream Gbp-Pq: Name regex-migration-to-pcre2.patch --- diff --git a/src/modules/regex/Makefile b/src/modules/regex/Makefile index 3b8758a0..db036b67 100644 --- a/src/modules/regex/Makefile +++ b/src/modules/regex/Makefile @@ -5,20 +5,15 @@ auto_gen= NAME=regex.so ifeq ($(CROSS_COMPILE),) -PCRE_BUILDER = $(shell \ - if pkg-config --exists libcre; then \ - echo 'pkg-config libpcre'; \ - else \ - which pcre-config; \ - fi) +PCRE_BUILDER = $(shell command -v pcre2-config) endif ifeq ($(PCRE_BUILDER),) PCREDEFS=-I$(LOCALBASE)/include - PCRELIBS=-L$(LOCALBASE)/lib -lpcre + PCRELIBS=-L$(LOCALBASE)/lib -lpcre2-8 else PCREDEFS = $(shell $(PCRE_BUILDER) --cflags) - PCRELIBS = $(shell $(PCRE_BUILDER) --libs) + PCRELIBS = $(shell $(PCRE_BUILDER) --libs8) endif DEFS+=$(PCREDEFS) diff --git a/src/modules/regex/regex_mod.c b/src/modules/regex/regex_mod.c index 2bc52104..c633a139 100644 --- a/src/modules/regex/regex_mod.c +++ b/src/modules/regex/regex_mod.c @@ -2,6 +2,7 @@ * regex module - pcre operations * * Copyright (C) 2008 Iñaki Baz Castillo + * Copyright (C) 2023 Victor Seva * * This file is part of Kamailio, a free SIP server. * @@ -32,7 +33,8 @@ #include #include #include -#include +#define PCRE2_CODE_UNIT_WIDTH 8 +#include #include "../../core/sr_module.h" #include "../../core/dprint.h" #include "../../core/pt.h" @@ -77,8 +79,11 @@ static int pcre_extended = 0; /* * Module internal parameter variables */ -static pcre **pcres; -static pcre ***pcres_addr; +static pcre2_general_context *pcres_gctx = NULL; +static pcre2_match_context *pcres_mctx = NULL; +static pcre2_compile_context *pcres_ctx = NULL; +static pcre2_code **pcres; +static pcre2_code ***pcres_addr; static int *num_pcres; static int pcre_options = 0x00000000; @@ -150,7 +155,16 @@ struct module_exports exports = { destroy /*!< destroy function */ }; +static void *pcre2_malloc(size_t size, void *ext) +{ + return shm_malloc(size); +} +static void pcre2_free(void *ptr, void *ext) +{ + shm_free(ptr); + ptr = NULL; +} /*! \brief * Init module function @@ -182,24 +196,39 @@ static int mod_init(void) /* PCRE options */ if (pcre_caseless != 0) { LM_DBG("PCRE CASELESS enabled\n"); - pcre_options = pcre_options | PCRE_CASELESS; + pcre_options = pcre_options | PCRE2_CASELESS; } if (pcre_multiline != 0) { LM_DBG("PCRE MULTILINE enabled\n"); - pcre_options = pcre_options | PCRE_MULTILINE; + pcre_options = pcre_options | PCRE2_MULTILINE; } if (pcre_dotall != 0) { LM_DBG("PCRE DOTALL enabled\n"); - pcre_options = pcre_options | PCRE_DOTALL; + pcre_options = pcre_options | PCRE2_DOTALL; } if (pcre_extended != 0) { LM_DBG("PCRE EXTENDED enabled\n"); - pcre_options = pcre_options | PCRE_EXTENDED; + pcre_options = pcre_options | PCRE2_EXTENDED; } LM_DBG("PCRE options: %i\n", pcre_options); + if((pcres_gctx = pcre2_general_context_create( + pcre2_malloc, pcre2_free, NULL)) + == NULL) { + LM_ERR("pcre2 general context creation failed\n"); + return -1; + } + if((pcres_ctx = pcre2_compile_context_create(pcres_gctx)) == NULL) { + LM_ERR("pcre2 compile context creation failed\n"); + return -1; + } + if((pcres_mctx = pcre2_match_context_create(pcres_gctx)) == NULL) { + LM_ERR("pcre2 match context creation failed\n"); + return -1; + } + /* Pointer to pcres */ - if ((pcres_addr = shm_malloc(sizeof(pcre **))) == 0) { + if ((pcres_addr = shm_malloc(sizeof(pcre2_code **))) == 0) { LM_ERR("no memory for pcres_addr\n"); goto err; } @@ -222,6 +251,18 @@ static int mod_init(void) err: free_shared_memory(); + + if(pcres_ctx) { + pcre2_compile_context_free(pcres_ctx); + } + + if(pcres_mctx) { + pcre2_match_context_free(pcres_mctx); + } + + if(pcres_gctx) { + pcre2_general_context_free(pcres_gctx); + } return -1; } @@ -239,13 +280,11 @@ static int load_pcres(int action) FILE *f; char line[FILE_MAX_LINE]; char **patterns = NULL; - pcre *pcre_tmp = NULL; - size_t pcre_size; - int pcre_rc; - const char *pcre_error; - int pcre_erroffset; + int pcre_error_num = 0; + char pcre_error[128]; + size_t pcre_erroffset; int num_pcres_tmp = 0; - pcre **pcres_tmp = NULL; + pcre2_code **pcres_tmp = NULL; int llen; /* Get the lock */ @@ -380,38 +419,35 @@ static int load_pcres(int action) } /* Temporal pointer of pcres */ - if ((pcres_tmp = pkg_malloc(sizeof(pcre *) * num_pcres_tmp)) == 0) { + if ((pcres_tmp = pkg_malloc(sizeof(pcre2_code *) * num_pcres_tmp)) == 0) { LM_ERR("no more memory for pcres_tmp\n"); goto err; } - for (i=0; is, pcre_options, &pcre_error, &pcre_erroffset, NULL); + pcre_re = pcre2_compile((PCRE2_SPTR)regex->s, PCRE2_ZERO_TERMINATED, + pcre_options, &pcre_error_num, &pcre_erroffset, pcres_ctx); if (pcre_re == NULL) { - LM_ERR("pcre_re compilation of '%s' failed at offset %d: %s\n", + switch(pcre2_get_error_message( + pcre_error_num, (PCRE2_UCHAR *)pcre_error, 128)) { + case PCRE2_ERROR_NOMEMORY: + snprintf(pcre_error, 128, + "unknown error[%d]: pcre2 error buffer too small", + pcre_error_num); + break; + case PCRE2_ERROR_BADDATA: + snprintf(pcre_error, 128, "unknown pcre2 error[%d]", + pcre_error_num); + break; + } + LM_ERR("pcre_re compilation of '%s' failed at offset %zu: %s\n", regex->s, pcre_erroffset, pcre_error); return -4; } - pcre_rc = pcre_exec( - pcre_re, /* the compiled pattern */ - NULL, /* no extra data - we didn't study the pattern */ - string->s, /* the matching string */ - (int)(string->len), /* the length of the subject */ - 0, /* start at offset 0 in the string */ - 0, /* default options */ - NULL, /* output vector for substring information */ - 0); /* number of elements in the output vector */ + pcre_md = pcre2_match_data_create_from_pattern(pcre_re, pcres_gctx); + pcre_rc = pcre2_match(pcre_re, /* the compiled pattern */ + (PCRE2_SPTR)string->s, /* the matching string */ + (PCRE2_SIZE)(string->len), /* the length of the subject */ + 0, /* start at offset 0 in the string */ + 0, /* default options */ + pcre_md, /* the match data block */ + pcres_mctx); /* a match context; NULL means use defaults */ /* Matching failed: handle error cases */ if (pcre_rc < 0) { switch(pcre_rc) { - case PCRE_ERROR_NOMATCH: + case PCRE2_ERROR_NOMATCH: LM_DBG("'%s' doesn't match '%s'\n", string->s, regex->s); break; default: - LM_DBG("matching error '%d'\n", pcre_rc); + switch(pcre2_get_error_message( + pcre_rc, (PCRE2_UCHAR *)pcre_error, 128)) { + case PCRE2_ERROR_NOMEMORY: + snprintf(pcre_error, 128, + "unknown error[%d]: pcre2 error buffer too " + "small", + pcre_rc); + break; + case PCRE2_ERROR_BADDATA: + snprintf(pcre_error, 128, "unknown pcre2 error[%d]", + pcre_rc); + break; + } + LM_ERR("matching error:'%s' failed[%d]\n", pcre_error, pcre_rc); break; } - pcre_free(pcre_re); + if(pcre_md) + pcre2_match_data_free(pcre_md); + pcre2_code_free(pcre_re); return -1; } - pcre_free(pcre_re); + if(pcre_md) + pcre2_match_data_free(pcre_md); + pcre2_code_free(pcre_re); LM_DBG("'%s' matches '%s'\n", string->s, regex->s); return 1; } @@ -595,6 +646,8 @@ static int w_pcre_match(struct sip_msg* _msg, char* _s1, char* _s2) static int ki_pcre_match_group(sip_msg_t* _msg, str* string, int num_pcre) { int pcre_rc; + pcre2_match_data *pcre_md = NULL; + char pcre_error[128]; /* Check if group matching feature is enabled */ if (file == NULL) { @@ -610,26 +663,41 @@ static int ki_pcre_match_group(sip_msg_t* _msg, str* string, int num_pcre) lock_get(reload_lock); - pcre_rc = pcre_exec( - (*pcres_addr)[num_pcre], /* the compiled pattern */ - NULL, /* no extra data - we didn't study the pattern */ - string->s, /* the matching string */ - (int)(string->len), /* the length of the subject */ - 0, /* start at offset 0 in the string */ - 0, /* default options */ - NULL, /* output vector for substring information */ - 0); /* number of elements in the output vector */ + pcre_md = pcre2_match_data_create_from_pattern( + (*pcres_addr)[num_pcre], pcres_gctx); + pcre_rc = pcre2_match((*pcres_addr)[num_pcre], /* the compiled pattern */ + (PCRE2_SPTR)string->s, /* the matching string */ + (PCRE2_SIZE)(string->len), /* the length of the subject */ + 0, /* start at offset 0 in the string */ + 0, /* default options */ + pcre_md, /* the match data block */ + pcres_mctx); /* a match context; NULL means use defaults */ lock_release(reload_lock); + if(pcre_md) + pcre2_match_data_free(pcre_md); /* Matching failed: handle error cases */ if (pcre_rc < 0) { switch(pcre_rc) { - case PCRE_ERROR_NOMATCH: + case PCRE2_ERROR_NOMATCH: LM_DBG("'%s' doesn't match pcres[%i]\n", string->s, num_pcre); break; default: - LM_DBG("matching error '%d'\n", pcre_rc); + switch(pcre2_get_error_message( + pcre_rc, (PCRE2_UCHAR *)pcre_error, 128)) { + case PCRE2_ERROR_NOMEMORY: + snprintf(pcre_error, 128, + "unknown error[%d]: pcre2 error buffer too " + "small", + pcre_rc); + break; + case PCRE2_ERROR_BADDATA: + snprintf(pcre_error, 128, "unknown pcre2 error[%d]", + pcre_rc); + break; + } + LM_ERR("matching error:'%s' failed[%d]\n", pcre_error, pcre_rc); break; } return -1;