mirror of
https://github.com/openwrt/telephony.git
synced 2025-05-01 14:00:29 +08:00

Backport merged patch and move package to PCRE2 as PCRE is EOL and won't receive any security updates anymore. Additional patch are backported to minimize changes to the backport patches. Only patch 010 required adaptation due to a fix backported in 5.7 in the same place where the patch fixed some whitespace issue. Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
457 lines
14 KiB
Diff
457 lines
14 KiB
Diff
From 374227b15ff7fbed8660beb93d52da15dcb4ba9e Mon Sep 17 00:00:00 2001
|
|
From: Victor Seva <linuxmaniac@torreviejawireless.org>
|
|
Date: Mon, 21 Aug 2023 12:27:43 +0200
|
|
Subject: [PATCH] dialplan: migrate to pcre2
|
|
|
|
---
|
|
src/modules/dialplan/Makefile | 11 +---
|
|
src/modules/dialplan/dialplan.c | 5 ++
|
|
src/modules/dialplan/dialplan.h | 20 ++++---
|
|
src/modules/dialplan/dp_db.c | 103 +++++++++++++++++++-------------
|
|
src/modules/dialplan/dp_repl.c | 56 +++++++++++------
|
|
5 files changed, 121 insertions(+), 74 deletions(-)
|
|
|
|
--- a/src/modules/dialplan/Makefile
|
|
+++ b/src/modules/dialplan/Makefile
|
|
@@ -6,20 +6,15 @@ auto_gen=
|
|
NAME=dialplan.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)
|
|
LIBS=$(PCRELIBS)
|
|
--- a/src/modules/dialplan/dialplan.c
|
|
+++ b/src/modules/dialplan/dialplan.c
|
|
@@ -5,6 +5,8 @@
|
|
*
|
|
* Copyright (C) 2014 Olle E. Johansson, Edvina AB
|
|
*
|
|
+ * Copyright (C) 2023 Victor Seva
|
|
+ *
|
|
* This file is part of Kamailio, a free SIP server.
|
|
*
|
|
* Kamailio is free software; you can redistribute it and/or modify
|
|
@@ -79,6 +81,9 @@ static int ki_dp_translate_vars(
|
|
int dp_replace_fixup(void **param, int param_no);
|
|
int dp_replace_fixup_free(void **param, int param_no);
|
|
|
|
+pcre2_general_context *dpl_gctx = NULL;
|
|
+pcre2_compile_context *dpl_ctx = NULL;
|
|
+
|
|
str dp_attr_pvar_s = STR_NULL;
|
|
pv_spec_t *dp_attr_pvar = NULL;
|
|
|
|
--- a/src/modules/dialplan/dialplan.h
|
|
+++ b/src/modules/dialplan/dialplan.h
|
|
@@ -13,8 +13,8 @@
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
- * You should have received a copy of the GNU General Public License
|
|
- * along with this program; if not, write to the Free Software
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
*/
|
|
@@ -30,7 +30,8 @@
|
|
#ifndef _DP_DIALPLAN_H
|
|
#define _DP_DIALPLAN_H
|
|
|
|
-#include <pcre.h>
|
|
+#define PCRE2_CODE_UNIT_WIDTH 8
|
|
+#include <pcre2.h>
|
|
#include "../../core/pvar.h"
|
|
#include "../../core/parser/msg_parser.h"
|
|
|
|
@@ -43,6 +44,9 @@
|
|
#define DP_TFLAGS_PV_MATCH (1 << 0)
|
|
#define DP_TFLAGS_PV_SUBST (1 << 1)
|
|
|
|
+extern pcre2_general_context *dpl_gctx;
|
|
+extern pcre2_compile_context *dpl_ctx;
|
|
+
|
|
typedef struct dpl_node
|
|
{
|
|
int dpid; /* dialplan id */
|
|
@@ -52,8 +56,8 @@ typedef struct dpl_node
|
|
str match_exp; /* match-first string */
|
|
str subst_exp; /* match string with subtitution groupping */
|
|
str repl_exp; /* replacement expression string */
|
|
- pcre *match_comp; /* compiled matching expression */
|
|
- pcre *subst_comp; /* compiled substitution expression */
|
|
+ pcre2_code *match_comp; /* compiled matching expression */
|
|
+ pcre2_code *subst_comp; /* compiled substitution expression */
|
|
struct subst_expr *repl_comp; /* compiled replacement */
|
|
str attrs; /* attributes string */
|
|
unsigned int tflags; /* flags for type of values for matching */
|
|
@@ -103,8 +107,8 @@ struct subst_expr *repl_exp_parse(str su
|
|
void repl_expr_free(struct subst_expr *se);
|
|
int dp_translate_helper(
|
|
sip_msg_t *msg, str *user_name, str *repl_user, dpl_id_p idp, str *);
|
|
-int rule_translate(
|
|
- sip_msg_t *msg, str *instr, dpl_node_t *rule, pcre *subst_comp, str *);
|
|
+int rule_translate(sip_msg_t *msg, str *instr, dpl_node_t *rule,
|
|
+ pcre2_code *subst_comp, str *);
|
|
|
|
-pcre *reg_ex_comp(const char *pattern, int *cap_cnt, int mtype);
|
|
+pcre2_code *reg_ex_comp(const char *pattern, int *cap_cnt, int mtype);
|
|
#endif
|
|
--- a/src/modules/dialplan/dp_db.c
|
|
+++ b/src/modules/dialplan/dp_db.c
|
|
@@ -196,11 +196,31 @@ void dp_disconnect_db(void)
|
|
}
|
|
}
|
|
|
|
+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;
|
|
+}
|
|
|
|
int init_data(void)
|
|
{
|
|
int *p;
|
|
|
|
+ if((dpl_gctx = pcre2_general_context_create(pcre2_malloc, pcre2_free, NULL))
|
|
+ == NULL) {
|
|
+ LM_ERR("pcre2 general context creation failed\n");
|
|
+ return -1;
|
|
+ }
|
|
+ if((dpl_ctx = pcre2_compile_context_create(dpl_gctx)) == NULL) {
|
|
+ LM_ERR("pcre2 compile context creation failed\n");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
dp_rules_hash = (dpl_id_p *)shm_malloc(2 * sizeof(dpl_id_p));
|
|
if(!dp_rules_hash) {
|
|
LM_ERR("out of shm memory\n");
|
|
@@ -227,6 +247,14 @@ int init_data(void)
|
|
|
|
void destroy_data(void)
|
|
{
|
|
+ if(dpl_ctx) {
|
|
+ pcre2_compile_context_free(dpl_ctx);
|
|
+ }
|
|
+
|
|
+ if(dpl_gctx) {
|
|
+ pcre2_general_context_free(dpl_gctx);
|
|
+ }
|
|
+
|
|
if(dp_rules_hash) {
|
|
destroy_hash(0);
|
|
destroy_hash(1);
|
|
@@ -373,55 +401,50 @@ int dpl_str_to_shm(str src, str *dest, i
|
|
|
|
|
|
/* Compile pcre pattern
|
|
- * if mtype==0 - return pointer to shm copy of result
|
|
- * if mtype==1 - return pcre pointer that has to be pcre_free() */
|
|
-pcre *reg_ex_comp(const char *pattern, int *cap_cnt, int mtype)
|
|
-{
|
|
- pcre *re, *result;
|
|
- const char *error;
|
|
- int rc, err_offset;
|
|
- size_t size;
|
|
+ * if mtype==0 - return pointer using shm
|
|
+ * if mtype==1 - return pcre2_code pointer that has to be pcre2_code_free() */
|
|
+pcre2_code *reg_ex_comp(const char *pattern, int *cap_cnt, int mtype)
|
|
+{
|
|
+ pcre2_code *re;
|
|
+ int pcre_error_num = 0;
|
|
+ char pcre_error[128];
|
|
+ size_t pcre_erroffset;
|
|
+ int rc;
|
|
|
|
- re = pcre_compile(pattern, 0, &error, &err_offset, NULL);
|
|
+ re = pcre2_compile((PCRE2_SPTR)pattern, PCRE2_ZERO_TERMINATED, 0,
|
|
+ &pcre_error_num, &pcre_erroffset, mtype == 0 ? dpl_ctx : NULL);
|
|
if(re == NULL) {
|
|
- LM_ERR("PCRE compilation of '%s' failed at offset %d: %s\n", pattern,
|
|
- err_offset, error);
|
|
- return (pcre *)0;
|
|
- }
|
|
- rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &size);
|
|
- if(rc != 0) {
|
|
- pcre_free(re);
|
|
- LM_ERR("pcre_fullinfo on compiled pattern '%s' yielded error: %d\n",
|
|
- pattern, rc);
|
|
- return (pcre *)0;
|
|
+ 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 compilation of '%s' failed at offset %zu: %s\n", pattern,
|
|
+ pcre_erroffset, pcre_error);
|
|
+ return NULL;
|
|
}
|
|
- rc = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, cap_cnt);
|
|
+ rc = pcre2_pattern_info(re, PCRE2_INFO_CAPTURECOUNT, cap_cnt);
|
|
if(rc != 0) {
|
|
- pcre_free(re);
|
|
+ pcre2_code_free(re);
|
|
LM_ERR("pcre_fullinfo on compiled pattern '%s' yielded error: %d\n",
|
|
pattern, rc);
|
|
- return (pcre *)0;
|
|
- }
|
|
- if(mtype == 0) {
|
|
- result = (pcre *)shm_malloc(size);
|
|
- if(result == NULL) {
|
|
- pcre_free(re);
|
|
- LM_ERR("not enough shared memory for compiled PCRE pattern\n");
|
|
- return (pcre *)0;
|
|
- }
|
|
- memcpy(result, re, size);
|
|
- pcre_free(re);
|
|
- return result;
|
|
- } else {
|
|
- return re;
|
|
+ return NULL;
|
|
}
|
|
+ return re;
|
|
}
|
|
|
|
|
|
/*compile the expressions, and if ok, build the rule */
|
|
dpl_node_t *build_rule(db_val_t *values)
|
|
{
|
|
- pcre *match_comp, *subst_comp;
|
|
+ pcre2_code *match_comp, *subst_comp;
|
|
struct subst_expr *repl_comp;
|
|
dpl_node_t *new_rule;
|
|
str match_exp, subst_exp, repl_exp, attrs;
|
|
@@ -544,9 +567,9 @@ dpl_node_t *build_rule(db_val_t *values)
|
|
|
|
err:
|
|
if(match_comp)
|
|
- shm_free(match_comp);
|
|
+ pcre2_code_free(match_comp);
|
|
if(subst_comp)
|
|
- shm_free(subst_comp);
|
|
+ pcre2_code_free(subst_comp);
|
|
if(repl_comp)
|
|
repl_expr_free(repl_comp);
|
|
if(new_rule)
|
|
@@ -692,10 +715,10 @@ void destroy_rule(dpl_node_t *rule)
|
|
LM_DBG("destroying rule with priority %i\n", rule->pr);
|
|
|
|
if(rule->match_comp)
|
|
- shm_free(rule->match_comp);
|
|
+ pcre2_code_free(rule->match_comp);
|
|
|
|
if(rule->subst_comp)
|
|
- shm_free(rule->subst_comp);
|
|
+ pcre2_code_free(rule->subst_comp);
|
|
|
|
/*destroy repl_exp*/
|
|
if(rule->repl_comp)
|
|
--- a/src/modules/dialplan/dp_repl.c
|
|
+++ b/src/modules/dialplan/dp_repl.c
|
|
@@ -15,8 +15,8 @@
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
- * You should have received a copy of the GNU General Public License
|
|
- * along with this program; if not, write to the Free Software
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
*/
|
|
@@ -38,7 +38,7 @@
|
|
|
|
typedef struct dpl_dyn_pcre
|
|
{
|
|
- pcre *re;
|
|
+ pcre2_code *re;
|
|
int cnt;
|
|
str expr;
|
|
|
|
@@ -186,9 +186,10 @@ int dpl_detect_avp_indx(const pv_elem_p
|
|
return 0;
|
|
}
|
|
|
|
-pcre *dpl_dyn_pcre_comp(sip_msg_t *msg, str *expr, str *vexpr, int *cap_cnt)
|
|
+pcre2_code *dpl_dyn_pcre_comp(
|
|
+ sip_msg_t *msg, str *expr, str *vexpr, int *cap_cnt)
|
|
{
|
|
- pcre *re = NULL;
|
|
+ pcre2_code *re = NULL;
|
|
int ccnt = 0;
|
|
|
|
if(expr == NULL || expr->s == NULL || expr->len <= 0 || vexpr == NULL
|
|
@@ -225,7 +226,7 @@ dpl_dyn_pcre_p dpl_dynamic_pcre_list(sip
|
|
dpl_dyn_pcre_p rt = NULL;
|
|
struct str_list *l = NULL;
|
|
struct str_list *t = NULL;
|
|
- pcre *re = NULL;
|
|
+ pcre2_code *re = NULL;
|
|
int cnt = 0;
|
|
str vexpr = STR_NULL;
|
|
|
|
@@ -294,7 +295,7 @@ error:
|
|
while(re_list) {
|
|
rt = re_list->next;
|
|
if(re_list->re)
|
|
- pcre_free(re_list->re);
|
|
+ pcre2_code_free(re_list->re);
|
|
pkg_free(re_list);
|
|
re_list = rt;
|
|
}
|
|
@@ -400,15 +401,16 @@ error:
|
|
#define MAX_PHONE_NB_DIGITS 127
|
|
static char dp_output_buf[MAX_PHONE_NB_DIGITS + 1];
|
|
int rule_translate(sip_msg_t *msg, str *instr, dpl_node_t *rule,
|
|
- pcre *subst_comp, str *result)
|
|
+ pcre2_code *subst_comp, str *result)
|
|
{
|
|
int repl_nb, offset, match_nb, rc, cap_cnt;
|
|
struct replace_with token;
|
|
struct subst_expr *repl_comp;
|
|
+ pcre2_match_data *pcre_md = NULL;
|
|
str match;
|
|
pv_value_t sv;
|
|
str *uri;
|
|
- int ovector[3 * (MAX_REPLACE_WITH + 1)];
|
|
+ PCRE2_SIZE *ovector = NULL;
|
|
char *p;
|
|
int size;
|
|
|
|
@@ -424,7 +426,7 @@ int rule_translate(sip_msg_t *msg, str *
|
|
|
|
if(subst_comp) {
|
|
/*just in case something went wrong at load time*/
|
|
- rc = pcre_fullinfo(subst_comp, NULL, PCRE_INFO_CAPTURECOUNT, &cap_cnt);
|
|
+ rc = pcre2_pattern_info(subst_comp, PCRE2_INFO_CAPTURECOUNT, &cap_cnt);
|
|
if(rc != 0) {
|
|
LM_ERR("pcre_fullinfo on compiled pattern yielded error: %d\n", rc);
|
|
return -1;
|
|
@@ -441,15 +443,19 @@ int rule_translate(sip_msg_t *msg, str *
|
|
}
|
|
|
|
/*search for the pattern from the compiled subst_exp*/
|
|
- if(pcre_exec(subst_comp, NULL, instr->s, instr->len, 0, 0, ovector,
|
|
- 3 * (MAX_REPLACE_WITH + 1))
|
|
+ pcre_md = pcre2_match_data_create_from_pattern(subst_comp, NULL);
|
|
+ if(pcre2_match(subst_comp, (PCRE2_SPTR)instr->s, (PCRE2_SIZE)instr->len,
|
|
+ 0, 0, pcre_md, NULL)
|
|
<= 0) {
|
|
LM_DBG("the string %.*s matched "
|
|
"the match_exp %.*s but not the subst_exp %.*s!\n",
|
|
instr->len, instr->s, rule->match_exp.len,
|
|
rule->match_exp.s, rule->subst_exp.len, rule->subst_exp.s);
|
|
+ if(pcre_md)
|
|
+ pcre2_match_data_free(pcre_md);
|
|
return -1;
|
|
}
|
|
+ ovector = pcre2_get_ovector_pointer(pcre_md);
|
|
}
|
|
|
|
/*simply copy from the replacing string*/
|
|
@@ -463,6 +469,8 @@ int rule_translate(sip_msg_t *msg, str *
|
|
memcpy(result->s, repl_comp->replacement.s, repl_comp->replacement.len);
|
|
result->len = repl_comp->replacement.len;
|
|
result->s[result->len] = '\0';
|
|
+ if(pcre_md)
|
|
+ pcre2_match_data_free(pcre_md);
|
|
return 0;
|
|
}
|
|
|
|
@@ -571,11 +579,15 @@ int rule_translate(sip_msg_t *msg, str *
|
|
}
|
|
|
|
result->s[result->len] = '\0';
|
|
+ if(pcre_md)
|
|
+ pcre2_match_data_free(pcre_md);
|
|
return 0;
|
|
|
|
error:
|
|
result->s = 0;
|
|
result->len = 0;
|
|
+ if(pcre_md)
|
|
+ pcre2_match_data_free(pcre_md);
|
|
return -1;
|
|
}
|
|
|
|
@@ -584,6 +596,7 @@ static char dp_attrs_buf[DP_MAX_ATTRS_LE
|
|
int dp_translate_helper(
|
|
sip_msg_t *msg, str *input, str *output, dpl_id_p idp, str *attrs)
|
|
{
|
|
+ pcre2_match_data *pcre_md = NULL;
|
|
dpl_node_p rulep;
|
|
dpl_index_p indexp;
|
|
int user_len, rez;
|
|
@@ -624,21 +637,28 @@ search_rule:
|
|
rez = -1;
|
|
do {
|
|
if(rez < 0) {
|
|
- rez = pcre_exec(re_list->re, NULL, input->s,
|
|
- input->len, 0, 0, NULL, 0);
|
|
+ pcre_md = pcre2_match_data_create_from_pattern(
|
|
+ re_list->re, NULL);
|
|
+ rez = pcre2_match(re_list->re, (PCRE2_SPTR)input->s,
|
|
+ (PCRE2_SIZE)input->len, 0, 0, pcre_md,
|
|
+ NULL);
|
|
LM_DBG("match check: [%.*s] %d\n",
|
|
re_list->expr.len, re_list->expr.s, rez);
|
|
} else
|
|
LM_DBG("match check skipped: [%.*s] %d\n",
|
|
re_list->expr.len, re_list->expr.s, rez);
|
|
rt = re_list->next;
|
|
- pcre_free(re_list->re);
|
|
+ pcre2_match_data_free(pcre_md);
|
|
+ pcre2_code_free(re_list->re);
|
|
pkg_free(re_list);
|
|
re_list = rt;
|
|
} while(re_list);
|
|
} else {
|
|
- rez = pcre_exec(rulep->match_comp, NULL, input->s,
|
|
- input->len, 0, 0, NULL, 0);
|
|
+ pcre_md = pcre2_match_data_create_from_pattern(
|
|
+ rulep->match_comp, NULL);
|
|
+ rez = pcre2_match(rulep->match_comp, (PCRE2_SPTR)input->s,
|
|
+ (PCRE2_SIZE)input->len, 0, 0, pcre_md, 0);
|
|
+ pcre2_match_data_free(pcre_md);
|
|
}
|
|
break;
|
|
|
|
@@ -728,7 +748,7 @@ repl:
|
|
LM_DBG("subst check skipped: [%.*s] %d\n", re_list->expr.len,
|
|
re_list->expr.s, rez);
|
|
rt = re_list->next;
|
|
- pcre_free(re_list->re);
|
|
+ pcre2_code_free(re_list->re);
|
|
pkg_free(re_list);
|
|
re_list = rt;
|
|
} while(re_list);
|