diff --git a/shadowsocksr-libev/patches/104-fix-use-after-free.patch b/shadowsocksr-libev/patches/104-pointer-used-after-free.patch similarity index 91% rename from shadowsocksr-libev/patches/104-fix-use-after-free.patch rename to shadowsocksr-libev/patches/104-pointer-used-after-free.patch index d00d549e3..9081d5560 100644 --- a/shadowsocksr-libev/patches/104-fix-use-after-free.patch +++ b/shadowsocksr-libev/patches/104-pointer-used-after-free.patch @@ -1,6 +1,6 @@ --- a/server/server.c +++ b/server/server.c -@@ -1942,11 +1942,11 @@ main(int argc, char **argv) +@@ -1942,12 +1942,12 @@ text = (char*)malloc(strlen(protocol) - 11); memcpy(text, protocol, strlen(protocol) - 11); int length = strlen(protocol) - 11; @@ -9,7 +9,8 @@ memset(protocol, 0x00, length); memcpy(protocol, text, length); LOGI("protocol compatible enable, %s", protocol); -+ free(protocol); free(text); ++ free(protocol); protocol_compatible = 1; } + } diff --git a/shadowsocksr-libev/src/server/Makefile.in b/shadowsocksr-libev/src/server/Makefile.in index 3bfa53eaa..17dad9597 100644 --- a/shadowsocksr-libev/src/server/Makefile.in +++ b/shadowsocksr-libev/src/server/Makefile.in @@ -105,7 +105,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_pthread.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/mbedtls.m4 \ - $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/pcre.m4 \ + $(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/pcre2.m4 \ $(top_srcdir)/m4/polarssl.m4 \ $(top_srcdir)/m4/stack-protector.m4 $(top_srcdir)/m4/zlib.m4 \ $(top_srcdir)/libev/libev.m4 $(top_srcdir)/configure.ac diff --git a/shadowsocksr-libev/src/server/rule.c b/shadowsocksr-libev/src/server/rule.c index 8aae04ea7..41ba5e7d9 100644 --- a/shadowsocksr-libev/src/server/rule.c +++ b/shadowsocksr-libev/src/server/rule.c @@ -82,14 +82,28 @@ 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; } } @@ -109,8 +123,15 @@ lookup_rule(const struct cork_dllist *rules, const char *name, size_t name_len) 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; } @@ -131,7 +152,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); } diff --git a/shadowsocksr-libev/src/server/rule.h b/shadowsocksr-libev/src/server/rule.h index 015bc42b5..84a89af67 100644 --- a/shadowsocksr-libev/src/server/rule.h +++ b/shadowsocksr-libev/src/server/rule.h @@ -33,17 +33,27 @@ #include -#ifdef HAVE_PCRE_H -#include -#elif HAVE_PCRE_PCRE_H -#include -#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 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;