openwrt-packages/net/shadowsocks-libev/patches/100-Upgrade-PCRE-to-PCRE2.p...

545 lines
17 KiB
Diff

From d4f4d9761cbd41c3ab6de79383ff39b9f97bf452 Mon Sep 17 00:00:00 2001
From: Syrone Wong <wong.syrone@gmail.com>
Date: Sat, 18 Nov 2017 20:06:50 +0800
Subject: [PATCH] Upgrade PCRE to PCRE2
- Use 8bit variant by default
This comes from a PR closed and never reopen as at times PCRE2 was too
new(???.)
Ref: https://github.com/shadowsocks/shadowsocks-libev/pull/1792
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
[ squash the first 2 patch from PR, drop the last one ]
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
.travis.yml | 9 ++-
configure.ac | 8 +--
m4/pcre.m4 | 152 ------------------------------------------
m4/pcre2.m4 | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++
src/rule.c | 53 ++++++++++++---
src/rule.h | 23 +++++--
6 files changed, 253 insertions(+), 173 deletions(-)
delete mode 100644 m4/pcre.m4
create mode 100644 m4/pcre2.m4
# diff --git a/.travis.yml b/.travis.yml
# index ee3424c..e7da08c 100644
# --- a/.travis.yml
# +++ b/.travis.yml
# @@ -11,11 +11,12 @@ env:
# global:
# - LIBSODIUM_VER=1.0.12
# - MBEDTLS_VER=2.4.0
# + - PCRE2_VER=10.30
# before_install:
# - |
# if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
# # All dependencies for macOS build. Some packages has been installed by travis so use reinstall.
# - brew reinstall autoconf automake xmlto c-ares libev mbedtls libsodium asciidoc >> /dev/null 2>&1;
# + brew reinstall autoconf automake xmlto pcre2 c-ares libev mbedtls libsodium asciidoc >> /dev/null 2>&1;
# else
# wget https://github.com/jedisct1/libsodium/releases/download/$LIBSODIUM_VER/libsodium-$LIBSODIUM_VER.tar.gz;
# tar xvf libsodium-$LIBSODIUM_VER.tar.gz;
# @@ -29,6 +30,12 @@ before_install:
# make SHARED=1;
# sudo make install;
# popd;
# + wget https://ftp.pcre.org/pub/pcre/pcre2-$PCRE2_VER.tar.gz;
# + tar xvf pcre2-$PCRE2_VER.tar.gz;
# + pushd pcre2-$PCRE2_VER;
# + ./configure --prefix=/usr --enable-pcre2-16 --enable-pcre2-32 && make;
# + sudo make install;
# + popd;
# # Load cached docker images
# if [[ -d $HOME/docker ]]; then
# ls $HOME/docker/*.tar.gz | xargs -I {file} sh -c "zcat {file} | docker load";
--- a/configure.ac
+++ b/configure.ac
@@ -20,10 +20,10 @@ AC_DISABLE_STATIC
AC_DISABLE_SHARED
LT_INIT([dlopen])
-dnl Check for pcre library
-TS_CHECK_PCRE
-if test "x${enable_pcre}" != "xyes"; then
- AC_MSG_ERROR([Cannot find pcre library. Configure --with-pcre=DIR])
+dnl Check for pcre2 library
+TS_CHECK_PCRE2
+if test "x${enable_pcre2}" != "xyes"; then
+ AC_MSG_ERROR([Cannot find pcre2 library. Configure --with-pcre2=DIR])
fi
dnl Checks for using shared libraries from system
--- a/m4/pcre.m4
+++ /dev/null
@@ -1,152 +0,0 @@
-dnl -------------------------------------------------------- -*- autoconf -*-
-dnl Licensed to the Apache Software Foundation (ASF) under one or more
-dnl contributor license agreements. See the NOTICE file distributed with
-dnl this work for additional information regarding copyright ownership.
-dnl The ASF licenses this file to You under the Apache License, Version 2.0
-dnl (the "License"); you may not use this file except in compliance with
-dnl the License. You may obtain a copy of the License at
-dnl
-dnl http://www.apache.org/licenses/LICENSE-2.0
-dnl
-dnl Unless required by applicable law or agreed to in writing, software
-dnl distributed under the License is distributed on an "AS IS" BASIS,
-dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-dnl See the License for the specific language governing permissions and
-dnl limitations under the License.
-
-dnl
-dnl TS_ADDTO(variable, value)
-dnl
-dnl Add value to variable
-dnl
-AC_DEFUN([TS_ADDTO], [
- if test "x$$1" = "x"; then
- test "x$verbose" = "xyes" && echo " setting $1 to \"$2\""
- $1="$2"
- else
- ats_addto_bugger="$2"
- for i in $ats_addto_bugger; do
- ats_addto_duplicate="0"
- for j in $$1; do
- if test "x$i" = "x$j"; then
- ats_addto_duplicate="1"
- break
- fi
- done
- if test $ats_addto_duplicate = "0"; then
- test "x$verbose" = "xyes" && echo " adding \"$i\" to $1"
- $1="$$1 $i"
- fi
- done
- fi
-])dnl
-
-dnl
-dnl TS_ADDTO_RPATH(path)
-dnl
-dnl Adds path to variable with the '-rpath' directive.
-dnl
-AC_DEFUN([TS_ADDTO_RPATH], [
- AC_MSG_NOTICE([adding $1 to RPATH])
- TS_ADDTO(LIBTOOL_LINK_FLAGS, [-R$1])
-])dnl
-
-dnl
-dnl pcre.m4: Trafficserver's pcre autoconf macros
-dnl
-
-dnl
-dnl TS_CHECK_PCRE: look for pcre libraries and headers
-dnl
-AC_DEFUN([TS_CHECK_PCRE], [
-enable_pcre=no
-AC_ARG_WITH(pcre, [AC_HELP_STRING([--with-pcre=DIR],[use a specific pcre library])],
-[
- if test "x$withval" != "xyes" && test "x$withval" != "x"; then
- pcre_base_dir="$withval"
- if test "$withval" != "no"; then
- enable_pcre=yes
- case "$withval" in
- *":"*)
- pcre_include="`echo $withval |sed -e 's/:.*$//'`"
- pcre_ldflags="`echo $withval |sed -e 's/^.*://'`"
- AC_MSG_CHECKING(checking for pcre includes in $pcre_include libs in $pcre_ldflags )
- ;;
- *)
- pcre_include="$withval/include"
- pcre_ldflags="$withval/lib"
- AC_MSG_CHECKING(checking for pcre includes in $withval)
- ;;
- esac
- fi
- fi
-],
-[
- AC_CHECK_PROG(PCRE_CONFIG, pcre-config, pcre-config)
- if test "x$PCRE_CONFIG" != "x"; then
- enable_pcre=yes
- pcre_base_dir="`$PCRE_CONFIG --prefix`"
- pcre_include="`$PCRE_CONFIG --cflags | sed -es/-I//`"
- pcre_ldflags="`$PCRE_CONFIG --libs | sed -es/-lpcre// -es/-L//`"
- fi
-])
-
-if test "x$pcre_base_dir" = "x"; then
- AC_MSG_CHECKING([for pcre location])
- AC_CACHE_VAL(ats_cv_pcre_dir,[
- for dir in /usr/local /usr ; do
- if test -d $dir && ( test -f $dir/include/pcre.h || test -f $dir/include/pcre/pcre.h ); then
- ats_cv_pcre_dir=$dir
- break
- fi
- done
- ])
- pcre_base_dir=$ats_cv_pcre_dir
- if test "x$pcre_base_dir" = "x"; then
- enable_pcre=no
- AC_MSG_RESULT([not found])
- else
- enable_pcre=yes
- pcre_include="$pcre_base_dir/include"
- pcre_ldflags="$pcre_base_dir/lib"
- AC_MSG_RESULT([$pcre_base_dir])
- fi
-else
- AC_MSG_CHECKING(for pcre headers in $pcre_include)
- if test -d $pcre_include && test -d $pcre_ldflags && ( test -f $pcre_include/pcre.h || test -f $pcre_include/pcre/pcre.h ); then
- AC_MSG_RESULT([ok])
- else
- AC_MSG_RESULT([not found])
- fi
-fi
-
-pcreh=0
-pcre_pcreh=0
-if test "$enable_pcre" != "no"; then
- saved_ldflags=$LDFLAGS
- saved_cppflags=$CFLAGS
- pcre_have_headers=0
- pcre_have_libs=0
- if test "$pcre_base_dir" != "/usr"; then
- TS_ADDTO(CFLAGS, [-I${pcre_include}])
- TS_ADDTO(CFLAGS, [-DPCRE_STATIC])
- TS_ADDTO(LDFLAGS, [-L${pcre_ldflags}])
- TS_ADDTO_RPATH(${pcre_ldflags})
- fi
- AC_SEARCH_LIBS([pcre_exec], [pcre], [pcre_have_libs=1])
- if test "$pcre_have_libs" != "0"; then
- AC_CHECK_HEADERS(pcre.h, [pcre_have_headers=1])
- AC_CHECK_HEADERS(pcre/pcre.h, [pcre_have_headers=1])
- fi
- if test "$pcre_have_headers" != "0"; then
- AC_DEFINE(HAVE_LIBPCRE,1,[Compiling with pcre support])
- AC_SUBST(LIBPCRE, [-lpcre])
- else
- enable_pcre=no
- CFLAGS=$saved_cppflags
- LDFLAGS=$saved_ldflags
- fi
-fi
-AC_SUBST(pcreh)
-AC_SUBST(pcre_pcreh)
-])
--- /dev/null
+++ b/m4/pcre2.m4
@@ -0,0 +1,181 @@
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Licensed to the Apache Software Foundation (ASF) under one or more
+dnl contributor license agreements. See the NOTICE file distributed with
+dnl this work for additional information regarding copyright ownership.
+dnl The ASF licenses this file to You under the Apache License, Version 2.0
+dnl (the "License"); you may not use this file except in compliance with
+dnl the License. You may obtain a copy of the License at
+dnl
+dnl http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+dnl Modified by Syrone Wong <wong.syrone@gmail.com> to support pcre2 8bit variant only
+
+dnl
+dnl TS_ADDTO(variable, value)
+dnl
+dnl Add value to variable
+dnl
+AC_DEFUN([TS_ADDTO], [
+ if test "x$$1" = "x"; then
+ test "x$verbose" = "xyes" && echo " setting $1 to \"$2\""
+ $1="$2"
+ else
+ ats_addto_bugger="$2"
+ for i in $ats_addto_bugger; do
+ ats_addto_duplicate="0"
+ for j in $$1; do
+ if test "x$i" = "x$j"; then
+ ats_addto_duplicate="1"
+ break
+ fi
+ done
+ if test $ats_addto_duplicate = "0"; then
+ test "x$verbose" = "xyes" && echo " adding \"$i\" to $1"
+ $1="$$1 $i"
+ fi
+ done
+ fi
+])dnl
+
+dnl
+dnl TS_ADDTO_RPATH(path)
+dnl
+dnl Adds path to variable with the '-rpath' directive.
+dnl
+AC_DEFUN([TS_ADDTO_RPATH], [
+ AC_MSG_NOTICE([adding $1 to RPATH])
+ TS_ADDTO(LIBTOOL_LINK_FLAGS, [-R$1])
+])dnl
+
+dnl
+dnl pcre2.m4: Trafficserver's pcre2 autoconf macros
+dnl
+
+dnl
+dnl TS_CHECK_PCRE2: look for pcre2 libraries and headers
+dnl
+AC_DEFUN([TS_CHECK_PCRE2], [
+enable_pcre2=no
+AC_ARG_WITH(pcre2, [AC_HELP_STRING([--with-pcre2=DIR],[use a specific pcre2 library])],
+[
+ if test "x$withval" != "xyes" && test "x$withval" != "x"; then
+ pcre2_base_dir="$withval"
+ if test "$withval" != "no"; then
+ enable_pcre2=yes
+ case "$withval" in
+ *":"*)
+ pcre2_include="`echo $withval |sed -e 's/:.*$//'`"
+ pcre2_ldflags="`echo $withval |sed -e 's/^.*://'`"
+ AC_MSG_CHECKING(checking for pcre2 includes in $pcre2_include libs in $pcre2_ldflags )
+ ;;
+ *)
+ pcre2_include="$withval/include"
+ pcre2_ldflags="$withval/lib"
+ AC_MSG_CHECKING(checking for pcre2 includes in $withval)
+ ;;
+ esac
+ fi
+ fi
+],
+[
+ AC_CHECK_PROG(PCRE2_CONFIG, pcre2-config, pcre2-config)
+ if test "x$PCRE2_CONFIG" != "x"; then
+ enable_pcre2=yes
+ pcre2_base_dir="`$PCRE2_CONFIG --prefix`"
+ pcre2_include="`$PCRE2_CONFIG --cflags | sed -es/-I//`"
+ pcre2_ldflags="`$PCRE2_CONFIG --libs8 | sed -es/-lpcre2-8// -es/-L//`"
+ fi
+])
+
+if test "x$pcre2_base_dir" = "x"; then
+ AC_MSG_CHECKING([for pcre2 location])
+ AC_CACHE_VAL(ats_cv_pcre2_dir,[
+ for dir in /usr/local /usr ; do
+ if test -d $dir && ( test -f $dir/include/pcre2.h || test -f $dir/include/pcre2/pcre2.h ); then
+ ats_cv_pcre2_dir=$dir
+ break
+ fi
+ done
+ ])
+ pcre2_base_dir=$ats_cv_pcre2_dir
+ if test "x$pcre2_base_dir" = "x"; then
+ enable_pcre2=no
+ AC_MSG_RESULT([not found])
+ else
+ enable_pcre2=yes
+ pcre2_include="$pcre2_base_dir/include"
+ pcre2_ldflags="$pcre2_base_dir/lib"
+ AC_MSG_RESULT([$pcre2_base_dir])
+ fi
+else
+ AC_MSG_CHECKING(for pcre2 headers in $pcre2_include)
+ if test -d $pcre2_include && test -d $pcre2_ldflags && ( test -f $pcre2_include/pcre2.h || test -f $pcre2_include/pcre2/pcre2.h ); then
+ AC_MSG_RESULT([ok])
+ else
+ AC_MSG_RESULT([not found])
+ fi
+fi
+
+pcre2h=0
+pcre2_pcre2h=0
+if test "$enable_pcre2" != "no"; then
+ saved_ldflags=$LDFLAGS
+ saved_cppflags=$CFLAGS
+ pcre2_have_headers=0
+ pcre2_have_libs=0
+ if test "$pcre2_base_dir" != "/usr"; then
+ TS_ADDTO(CFLAGS, [-I${pcre2_include}])
+ TS_ADDTO(CFLAGS, [-DPCRE2_STATIC])
+ TS_ADDTO(LDFLAGS, [-L${pcre2_ldflags}])
+ TS_ADDTO_RPATH(${pcre2_ldflags})
+ fi
+ AC_SEARCH_LIBS([pcre2_match_8], [pcre2-8], [pcre2_have_libs=1])
+ if test "$pcre2_have_libs" != "0"; then
+ AC_MSG_CHECKING([pcre2.h])
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2.h>
+ ]],
+ [[
+ ]]
+ )],
+ [pcre2_have_headers=1
+ AC_MSG_RESULT([ok])],
+ [AC_MSG_RESULT([not found])]
+ )
+
+ AC_MSG_CHECKING([pcre2/pcre2.h])
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[
+#define PCRE2_CODE_UNIT_WIDTH 8
+#include <pcre2/pcre2.h>
+ ]],
+ [[
+ ]]
+ )],
+ [pcre2_have_headers=1
+ AC_MSG_RESULT([ok])],
+ [AC_MSG_RESULT([not found])]
+ )
+ fi
+ if test "$pcre2_have_headers" != "0"; then
+ AC_DEFINE(HAVE_LIBPCRE2,1,[Compiling with pcre2 support])
+ AC_SUBST(LIBPCRE2, [-lpcre2-8])
+ else
+ enable_pcre2=no
+ CFLAGS=$saved_cppflags
+ LDFLAGS=$saved_ldflags
+ fi
+fi
+AC_SUBST(pcre2h)
+AC_SUBST(pcre2_pcre2h)
+])
--- a/src/rule.c
+++ b/src/rule.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net>
* Copyright (c) 2011 Manuel Kasper <mk@neon1.net>
+ * Copyright (c) 2017 Syrone Wong <wong.syrone@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -74,18 +75,37 @@ add_rule(struct cork_dllist *rules, rule
cork_dllist_add(rules, &rule->entries);
}
+/*
+ * XXX: As pattern and subject are char arguments, they can be straightforwardly
+ * cast to PCRE2_SPTR as we are working in 8-bit code units.
+ */
+
int
init_rule(rule_t *rule)
{
if (rule->pattern_re == NULL) {
- const char *reerr;
- int reerroffset;
+ int errornumber;
+ PCRE2_SIZE erroroffset;
+ rule->pattern_re = pcre2_compile(
+ (PCRE2_SPTR)rule->pattern, /* the pattern */
+ PCRE2_ZERO_TERMINATED, /* indicates pattern is zero-terminated */
+ 0, /* default options */
+ &errornumber, /* for error number */
+ &erroroffset, /* for error offset */
+ NULL); /* use default compile context */
- rule->pattern_re =
- pcre_compile(rule->pattern, 0, &reerr, &reerroffset, NULL);
if (rule->pattern_re == NULL) {
- LOGE("Regex compilation of \"%s\" failed: %s, offset %d",
- rule->pattern, reerr, reerroffset);
+ PCRE2_UCHAR errbuffer[512];
+ pcre2_get_error_message(errornumber, errbuffer, sizeof(errbuffer));
+ LOGE("PCRE2 regex compilation failed at offset %d: %s\n", (int)erroroffset,
+ errbuffer);
+ return 0;
+ }
+
+ rule->pattern_re_match_data = pcre2_match_data_create_from_pattern(rule->pattern_re, NULL);
+
+ if (rule->pattern_re_match_data == NULL) {
+ ERROR("PCRE2: the memory for the block could not be obtained");
return 0;
}
}
@@ -105,8 +125,15 @@ lookup_rule(const struct cork_dllist *ru
cork_dllist_foreach_void(rules, curr, next) {
rule_t *rule = cork_container_of(curr, rule_t, entries);
- if (pcre_exec(rule->pattern_re, NULL,
- name, name_len, 0, 0, NULL, 0) >= 0)
+ if (pcre2_match(
+ rule->pattern_re, /* the compiled pattern */
+ (PCRE2_SPTR)name, /* the subject string */
+ name_len, /* the length of the subject */
+ 0, /* start at offset 0 in the subject */
+ 0, /* default options */
+ rule->pattern_re_match_data, /* block for storing the result */
+ NULL /* use default match context */
+ ) >= 0)
return rule;
}
@@ -127,7 +154,13 @@ free_rule(rule_t *rule)
return;
ss_free(rule->pattern);
- if (rule->pattern_re != NULL)
- pcre_free(rule->pattern_re);
+ if (rule->pattern_re != NULL) {
+ pcre2_code_free(rule->pattern_re); /* data and the compiled pattern. */
+ rule->pattern_re = NULL;
+ }
+ if (rule->pattern_re_match_data != NULL) {
+ pcre2_match_data_free(rule->pattern_re_match_data); /* Release memory used for the match */
+ rule->pattern_re_match_data = NULL;
+ }
ss_free(rule);
}
--- a/src/rule.h
+++ b/src/rule.h
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2011 and 2012, Dustin Lundquist <dustin@null-ptr.net>
* Copyright (c) 2011 Manuel Kasper <mk@neon1.net>
+ * Copyright (c) 2017 Syrone Wong <wong.syrone@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,17 +34,27 @@
#include <libcork/ds.h>
-#ifdef HAVE_PCRE_H
-#include <pcre.h>
-#elif HAVE_PCRE_PCRE_H
-#include <pcre/pcre.h>
-#endif
+/*
+ * The PCRE2_CODE_UNIT_WIDTH macro must be defined before including pcre2.h.
+ * For a program that uses only one code unit width, setting it to 8, 16, or 32
+ * makes it possible to use generic function names such as pcre2_compile(). Note
+ * that just changing 8 to 16 (for example) is not sufficient to convert this
+ * program to process 16-bit characters. Even in a fully 16-bit environment, where
+ * string-handling functions such as strcmp() and printf() work with 16-bit
+ * characters, the code for handling the table of named substrings will still need
+ * to be modified.
+ */
+/* we only need to support ASCII chartable, thus set it to 8 */
+#define PCRE2_CODE_UNIT_WIDTH 8
+
+#include <pcre2.h>
typedef struct rule {
char *pattern;
/* Runtime fields */
- pcre *pattern_re;
+ pcre2_code *pattern_re;
+ pcre2_match_data *pattern_re_match_data;
struct cork_dllist_item entries;
} rule_t;