Projects
Mega:24.03:SP1:Everything
nmap
_service:tar_scm:backport-upgrade-libpcre-to-PC...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:backport-upgrade-libpcre-to-PCRE2-10.42.patch of Package nmap
From 828ab48764b82d0226e860c73c5dac5b11f77385 Mon Sep 17 00:00:00 2001 From: dmiller <dmiller@e0a8ed71-7df4-0310-8962-fdc924857419> Date: Sat, 24 Jun 2023 01:53:07 +0000 Subject: [PATCH] Upgrade libpcre to PCRE2 10.42. Windows/macOS builds not completed. Conflict: Remove pcre2 source code modification, which can be replaced by pcre2-devel dependency Reference: https://github.com/nmap/nmap/commit/828ab48764b82d0226e860c73c5dac5b11f77385 --- checklibs.sh | 10 +- configure | 92 +++------ configure.ac | 23 +-- nmap.cc | 6 +- nmap_config.h.in | 2 - nping/nping_config.h.in | 2 - nse_pcrelib.cc | 400 ---------------------------------------- nse_pcrelib.h | 9 - nselib/pcre.luadoc | 135 -------------- service_scan.cc | 180 ++++++++++-------- service_scan.h | 33 ++-- 11 files changed, 156 insertions(+), 736 deletions(-) delete mode 100644 nse_pcrelib.cc delete mode 100644 nse_pcrelib.h delete mode 100644 nselib/pcre.luadoc diff --git a/checklibs.sh b/checklibs.sh index 2048e2a..26e9d8a 100644 --- a/checklibs.sh +++ b/checklibs.sh @@ -11,13 +11,13 @@ trim_version() { } check_libpcre() { - PCRE_SOURCE="https://sourceforge.net/projects/pcre/files/latest/download" + PCRE_SOURCE="https://github.com/PCRE2Project/pcre2/releases/latest" PCRE_MAJOR="" PCRE_MINOR="" - eval $(grep '^PCRE_MAJOR=' $NDIR/libpcre/configure) - eval $(grep '^PCRE_MINOR=' $NDIR/libpcre/configure) - PCRE_VERSION="$PCRE_MAJOR.$PCRE_MINOR" - PCRE_LATEST=$(curl -s -I $PCRE_SOURCE | perl -lne 'if(/pcre-(\d+.\d+).zip/){print $1}' | newest) + eval $(grep '^PCRE2_MAJOR=' $NDIR/libpcre/configure) + eval $(grep '^PCRE2_MINOR=' $NDIR/libpcre/configure) + PCRE_VERSION="$PCRE2_MAJOR.$PCRE2_MINOR" + PCRE_LATEST=$(curl -s -I $PCRE_SOURCE | tee tmp.txt | perl -lne 'if(m|^Location:.*/tag/pcre2-(\d+.\d+)[\r\n]*$|){print $1;exit(0)}') if [ "$PCRE_VERSION" != "$PCRE_LATEST" ]; then echo "Newer version of libpcre available" echo " Current:" $PCRE_VERSION diff --git a/configure b/configure index d1d2f19..12764ee 100755 --- a/configure +++ b/configure @@ -1451,8 +1451,8 @@ Optional Packages: [DIR]/lib/ and [DIR]/include/openssl/) --with-libpcap=DIR Look for pcap in DIR/include and DIR/libs. --with-libpcap=included Always use version included with Nmap - --with-libpcre=DIR Use an existing (compiled) pcre lib from DIR/include - and DIR/lib. + --with-libpcre=DIR Use an existing (compiled) pcre2 lib from + DIR/include and DIR/lib. --with-libpcre=included Always use the version included with Nmap --with-libz=DIR Use specific copy of libz --with-libz=included Always use version included with Nmap @@ -6437,58 +6437,19 @@ fi # If they didn't specify it, we try to find it if test $have_pcre != yes -a $requested_included_pcre != yes ; then - ac_fn_c_check_header_mongrel "$LINENO" "pcre.h" "ac_cv_header_pcre_h" "$ac_includes_default" -if test "x$ac_cv_header_pcre_h" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcre_version in -lpcre" >&5 -$as_echo_n "checking for pcre_version in -lpcre... " >&6; } -if ${ac_cv_lib_pcre_pcre_version+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lpcre $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ + ac_fn_c_check_header_compile "$LINENO" "pcre2.h" "ac_cv_header_pcre2_h" " +#define PCRE2_CODE_UNIT_WIDTH 8 -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char pcre_version (); -int -main () -{ -return pcre_version (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_pcre_pcre_version=yes -else - ac_cv_lib_pcre_pcre_version=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcre_pcre_version" >&5 -$as_echo "$ac_cv_lib_pcre_pcre_version" >&6; } -if test "x$ac_cv_lib_pcre_pcre_version" = xyes; then : - have_pcre=yes -fi -else - ac_fn_c_check_header_mongrel "$LINENO" "pcre/pcre.h" "ac_cv_header_pcre_pcre_h" "$ac_includes_default" -if test "x$ac_cv_header_pcre_pcre_h" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcre_version in -lpcre" >&5 -$as_echo_n "checking for pcre_version in -lpcre... " >&6; } -if ${ac_cv_lib_pcre_pcre_version+:} false; then : +" +if test "x$ac_cv_header_pcre2_h" = xyes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcre2_compile_8 in -lpcre2-8" >&5 +$as_echo_n "checking for pcre2_compile_8 in -lpcre2-8... " >&6; } +if ${ac_cv_lib_pcre2_8_pcre2_compile_8+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS -LIBS="-lpcre $LIBS" +LIBS="-lpcre2-8 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -6498,35 +6459,30 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #ifdef __cplusplus extern "C" #endif -char pcre_version (); +char pcre2_compile_8 (); int main () { -return pcre_version (); +return pcre2_compile_8 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_pcre_pcre_version=yes + ac_cv_lib_pcre2_8_pcre2_compile_8=yes else - ac_cv_lib_pcre_pcre_version=no + ac_cv_lib_pcre2_8_pcre2_compile_8=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcre_pcre_version" >&5 -$as_echo "$ac_cv_lib_pcre_pcre_version" >&6; } -if test "x$ac_cv_lib_pcre_pcre_version" = xyes; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcre2_8_pcre2_compile_8" >&5 +$as_echo "$ac_cv_lib_pcre2_8_pcre2_compile_8" >&6; } +if test "x$ac_cv_lib_pcre2_8_pcre2_compile_8" = xyes; then : have_pcre=yes fi - -fi - - - fi @@ -6536,8 +6492,8 @@ fi if test $have_pcre != yes ; then subdirs="$subdirs libpcre" - CPPFLAGS="-I\$(top_srcdir)/$LIBPCREDIR $CPPFLAGS" - LIBPCRE_LIBS="$LIBPCREDIR/libpcre.a" + CPPFLAGS="-I\$(top_srcdir)/$LIBPCREDIR/src $CPPFLAGS" + LIBPCRE_LIBS="$LIBPCREDIR/.libs/libpcre2-8.a" PCRE_BUILD="build-pcre" PCRE_CLEAN="clean-pcre" PCRE_DIST_CLEAN="distclean-pcre" @@ -6546,19 +6502,19 @@ $as_echo "#define PCRE_INCLUDED 1" >>confdefs.h else # We only need to check for and use this if we are NOT using included pcre - for ac_header in pcre/pcre.h + for ac_header in pcre2.h do : - ac_fn_c_check_header_mongrel "$LINENO" "pcre/pcre.h" "ac_cv_header_pcre_pcre_h" "$ac_includes_default" -if test "x$ac_cv_header_pcre_pcre_h" = xyes; then : + ac_fn_c_check_header_mongrel "$LINENO" "pcre2.h" "ac_cv_header_pcre2_h" "$ac_includes_default" +if test "x$ac_cv_header_pcre2_h" = xyes; then : cat >>confdefs.h <<_ACEOF -#define HAVE_PCRE_PCRE_H 1 +#define HAVE_PCRE2_H 1 _ACEOF fi done - LIBPCRE_LIBS="-lpcre" + LIBPCRE_LIBS="-lpcre2-8" PCRE_BUILD="" PCRE_CLEAN="" PCRE_DIST_CLEAN="" diff --git a/configure.ac b/configure.ac index 7835d9b..c25fb04 100644 --- a/configure.ac +++ b/configure.ac @@ -510,7 +510,7 @@ LIBPCREDIR=libpcre # First we test whether they specified libpcre explicitly AC_ARG_WITH(libpcre, -AC_HELP_STRING([--with-libpcre=DIR], [Use an existing (compiled) pcre lib from DIR/include and DIR/lib.]) +AC_HELP_STRING([--with-libpcre=DIR], [Use an existing (compiled) pcre2 lib from DIR/include and DIR/lib.]) AC_HELP_STRING([--with-libpcre=included], [Always use the version included with Nmap]), [ case "$with_libpcre" in yes) @@ -528,27 +528,28 @@ AC_HELP_STRING([--with-libpcre=included], [Always use the version included with # If they didn't specify it, we try to find it if test $have_pcre != yes -a $requested_included_pcre != yes ; then - AC_CHECK_HEADER(pcre.h, - AC_CHECK_LIB(pcre, pcre_version, [have_pcre=yes ]), - [AC_CHECK_HEADER(pcre/pcre.h, - [AC_CHECK_LIB(pcre, pcre_version, [have_pcre=yes])] - )] + AC_CHECK_HEADER(pcre2.h, + AC_CHECK_LIB(pcre2-8, pcre2_compile_8, [have_pcre=yes ]), + [], + [ +#define PCRE2_CODE_UNIT_WIDTH 8 + ] ) fi # If we still don't have it, we use our own if test $have_pcre != yes ; then AC_CONFIG_SUBDIRS( libpcre ) - CPPFLAGS="-I\$(top_srcdir)/$LIBPCREDIR $CPPFLAGS" - LIBPCRE_LIBS="$LIBPCREDIR/libpcre.a" + CPPFLAGS="-I\$(top_srcdir)/$LIBPCREDIR/src $CPPFLAGS" + LIBPCRE_LIBS="$LIBPCREDIR/.libs/libpcre2-8.a" PCRE_BUILD="build-pcre" PCRE_CLEAN="clean-pcre" PCRE_DIST_CLEAN="distclean-pcre" - AC_DEFINE(PCRE_INCLUDED, 1, [Using included libpcre]) + AC_DEFINE(PCRE_INCLUDED, 1, [Using included libpcre2]) else # We only need to check for and use this if we are NOT using included pcre - AC_CHECK_HEADERS(pcre/pcre.h) - LIBPCRE_LIBS="-lpcre" + AC_CHECK_HEADERS(pcre2.h) + LIBPCRE_LIBS="-lpcre2-8" PCRE_BUILD="" PCRE_CLEAN="" PCRE_DIST_CLEAN="" diff --git a/nmap.cc b/nmap.cc index e4c65e7..96f0230 100644 --- a/nmap.cc +++ b/nmap.cc @@ -2803,10 +2803,12 @@ static void display_nmap_version() { without.push_back("libz"); #endif + char pcre2_version[255]; + pcre2_config(PCRE2_CONFIG_VERSION, pcre2_version); #ifdef PCRE_INCLUDED - with.push_back(std::string("nmap-libpcre-") + get_word_or_quote(pcre_version(), 0)); + with.push_back(std::string("nmap-libpcre2-") + get_word_or_quote(pcre2_version, 0)); #else - with.push_back(std::string("libpcre-") + get_word_or_quote(pcre_version(), 0)); + with.push_back(std::string("libpcre2-") + get_word_or_quote(pcre2_version, 0)); #endif #ifdef WIN32 diff --git a/nmap_config.h.in b/nmap_config.h.in index 67dbeda..1dae65a 100644 --- a/nmap_config.h.in +++ b/nmap_config.h.in @@ -103,8 +103,6 @@ #undef HAVE_TERMIOS_H -#undef HAVE_PCRE_PCRE_H - #undef BSD_NETWORKING #undef IN_ADDR_DEEPSTRUCT diff --git a/nping/nping_config.h.in b/nping/nping_config.h.in index 98638cb..9b6f971 100644 --- a/nping/nping_config.h.in +++ b/nping/nping_config.h.in @@ -101,8 +101,6 @@ #undef HAVE_TERMIOS_H -#undef HAVE_PCRE_PCRE_H - #undef BSD_NETWORKING #undef IN_ADDR_DEEPSTRUCT diff --git a/nse_pcrelib.cc b/nse_pcrelib.cc deleted file mode 100644 index 436697e..0000000 --- a/nse_pcrelib.cc +++ /dev/null @@ -1,400 +0,0 @@ -/* lrexlib.c - PCRE regular expression library */ -/* Reuben Thomas nov00-18dec04 */ -/* Shmuel Zeigerman may04-18dec04 */ - - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "nse_lua.h" - -#include <locale.h> - -#include <nbase.h> - -#ifdef HAVE_PCRE_PCRE_H -# include <pcre/pcre.h> -#else -# include <pcre.h> -#endif - -#include "nse_pcrelib.h" - -static int get_startoffset(lua_State *L, int stackpos, size_t len) -{ - int startoffset = luaL_optinteger(L, stackpos, 1); - if(startoffset > 0) - startoffset--; - else if(startoffset < 0) { - startoffset += (int) len; - if(startoffset < 0) - startoffset = 0; - } - return startoffset; -} - -static int udata_tostring (lua_State *L, const char* type_handle, - const char* type_name) -{ - char buf[256]; - void *udata = luaL_checkudata(L, 1, type_handle); - - if(udata) { - (void)Snprintf(buf, 255, "%s (%p)", type_name, udata); - lua_pushstring(L, buf); - } - else { - (void)Snprintf(buf, 255, "must be userdata of type '%s'", type_name); - (void)luaL_argerror(L, 1, buf); - } - - free(udata); - return 1; -} - -typedef struct { const char* key; lua_Integer val; } flags_pair; - -static int get_flags (lua_State *L, const flags_pair *arr) -{ - const flags_pair *p; - lua_newtable(L); - for(p=arr; p->key != NULL; p++) { - lua_pushstring(L, p->key); - lua_pushinteger(L, p->val); - lua_rawset(L, -3); - } - return 1; -} - -const char pcre_handle[] = "pcre_regex_handle"; -const char pcre_typename[] = "pcre_regex"; - -typedef struct { - pcre *pr; - pcre_extra *extra; - int *match; - int ncapt; - const unsigned char *tables; -} pcre2; /* a better name is needed */ - -static const unsigned char *Lpcre_maketables(lua_State *L, int stackpos) -{ - const unsigned char *tables; - char old_locale[256]; - char *locale = strdup(luaL_checkstring(L, stackpos)); - - if(locale == NULL) - luaL_error(L, "cannot set locale"); - - strncpy(old_locale, setlocale(LC_CTYPE, NULL), 255); /* store the locale */ - - if(setlocale(LC_CTYPE, locale) == NULL) /* set new locale */ - luaL_error(L, "cannot set locale"); - - tables = pcre_maketables(); /* make tables with new locale */ - (void)setlocale(LC_CTYPE, old_locale); /* restore the old locale */ - - free(locale); - return tables; -} - -static int Lpcre_comp(lua_State *L) -{ - char buf[256]; - const char *error; - int erroffset; - pcre2 *ud; - const char *pattern = luaL_checkstring(L, 1); - int cflags = luaL_optinteger(L, 2, 0); - const unsigned char *tables = NULL; - - if(lua_gettop(L) > 2 && !lua_isnil(L, 3)) - tables = Lpcre_maketables(L, 3); - if(tables == NULL) - luaL_error(L, "PCRE compilation failed"); - - ud = (pcre2*)lua_newuserdata(L, sizeof(pcre2)); - luaL_getmetatable(L, pcre_handle); - (void)lua_setmetatable(L, -2); - ud->match = NULL; - ud->extra = NULL; - ud->tables = tables; /* keep this for eventual freeing */ - - ud->pr = pcre_compile(pattern, cflags, &error, &erroffset, tables); - if(!ud->pr) { - (void)Snprintf(buf, 255, "%s (pattern offset: %d)", error, erroffset+1); - /* show offset 1-based as it's common in Lua */ - luaL_error(L, buf); - } - - ud->extra = pcre_study(ud->pr, 0, &error); - if(error) luaL_error(L, error); - - pcre_fullinfo(ud->pr, ud->extra, PCRE_INFO_CAPTURECOUNT, &ud->ncapt); - /* need (2 ints per capture, plus one for substring match) * 3/2 */ - ud->match = (int *) safe_malloc((ud->ncapt + 1) * 3 * sizeof(int)); - - return 1; -} - -static void Lpcre_getargs(lua_State *L, pcre2 **pud, const char **text, - size_t *text_len) -{ - *pud = (pcre2 *)luaL_checkudata(L, 1, pcre_handle); - if(*pud == NULL) - (void)luaL_argerror(L, 1, ("compiled regexp expected")); - *text = luaL_checklstring(L, 2, text_len); -} - -typedef void (*Lpcre_push_matches) (lua_State *L, const char *text, pcre2 *ud); - -static void Lpcre_push_substrings (lua_State *L, const char *text, pcre2 *ud) -{ - unsigned int i, j; - unsigned int namecount; - unsigned char *name_table; - int name_entry_size; - unsigned char *tabptr; - const int *match = ud->match; - - lua_newtable(L); - for (i = 1; i <= (unsigned) ud->ncapt; i++) { - j = i * 2; - if (match[j] >= 0) - lua_pushlstring(L, text + match[j], (size_t)(match[j + 1] - match[j])); - else - lua_pushboolean(L, 0); - lua_rawseti(L, -2, i); - } - - /* now do named subpatterns - NJG */ - (void)pcre_fullinfo(ud->pr, ud->extra, PCRE_INFO_NAMECOUNT, &namecount); - if (namecount <= 0) - return; - (void)pcre_fullinfo(ud->pr, ud->extra, PCRE_INFO_NAMETABLE, &name_table); - (void)pcre_fullinfo(ud->pr, ud->extra, PCRE_INFO_NAMEENTRYSIZE, &name_entry_size); - tabptr = name_table; - for (i = 0; i < namecount; i++) { - unsigned int n = (tabptr[0] << 8) | tabptr[1]; /* number of the capturing parenthesis */ - if (n > 0 && n <= (unsigned) ud->ncapt) { /* check range */ - unsigned int j = n * 2; - lua_pushstring(L, (char*)tabptr + 2); /* name of the capture, zero terminated */ - if (match[j] >= 0) - lua_pushlstring(L, text + match[j], match[j + 1] - match[j]); - else - lua_pushboolean(L, 0); - lua_rawset(L, -3); - } - tabptr += name_entry_size; - } -} - -static void Lpcre_push_offsets (lua_State *L, const char *text, pcre2 * ud) -{ - unsigned int i, j, k; - if(text) { - /* suppress compiler warning */ - } - lua_newtable(L); - for (i=1, j=1; i <= (unsigned) ud->ncapt; i++) { - k = i * 2; - if (ud->match[k] >= 0) { - lua_pushinteger(L, ud->match[k] + 1); - lua_rawseti(L, -2, j++); - lua_pushinteger(L, ud->match[k+1]); - lua_rawseti(L, -2, j++); - } - else { - lua_pushboolean(L, 0); - lua_rawseti(L, -2, j++); - lua_pushboolean(L, 0); - lua_rawseti(L, -2, j++); - } - } -} - -static int Lpcre_match_generic(lua_State *L, Lpcre_push_matches push_matches) -{ - int res; - const char *text; - pcre2 *ud; - size_t elen; - int startoffset; - int eflags = luaL_optinteger(L, 4, 0); - - Lpcre_getargs(L, &ud, &text, &elen); - startoffset = get_startoffset(L, 3, elen); - - res = pcre_exec(ud->pr, ud->extra, text, (int)elen, startoffset, eflags, - ud->match, (ud->ncapt + 1) * 3); - if (res >= 0) { - lua_pushinteger(L, (lua_Number) ud->match[0] + 1); - lua_pushinteger(L, (lua_Number) ud->match[1]); - (*push_matches)(L, text, ud); - return 3; - } - return 0; -} - -static int Lpcre_match(lua_State *L) -{ - return Lpcre_match_generic(L, Lpcre_push_substrings); -} - -static int Lpcre_exec(lua_State *L) -{ - return Lpcre_match_generic(L, Lpcre_push_offsets); -} - -static int Lpcre_gmatch(lua_State *L) -{ - int res; - size_t len; - int nmatch = 0, limit = 0; - const char *text; - pcre2 *ud; - int maxmatch = luaL_optinteger(L, 4, 0); - int eflags = luaL_optinteger(L, 5, 0); - int startoffset = 0; - Lpcre_getargs(L, &ud, &text, &len); - luaL_checktype(L, 3, LUA_TFUNCTION); - - if(maxmatch > 0) /* this must be stated in the docs */ - limit = 1; - - while (!limit || nmatch < maxmatch) { - res = pcre_exec(ud->pr, ud->extra, text, (int)len, startoffset, eflags, - ud->match, (ud->ncapt + 1) * 3); - if (res >= 0) { - nmatch++; - lua_pushvalue(L, 3); - lua_pushlstring(L, text + ud->match[0], ud->match[1] - ud->match[0]); - Lpcre_push_substrings(L, text, ud); - lua_call(L, 2, 1); - if(lua_toboolean(L, -1)) - break; - lua_pop(L, 1); - startoffset = ud->match[1]; - } else - break; - } - lua_pushinteger(L, nmatch); - return 1; -} - -static int Lpcre_gc (lua_State *L) -{ - pcre2 *ud = (pcre2 *)luaL_checkudata(L, 1, pcre_handle); - if (ud) { - if(ud->pr) pcre_free(ud->pr); - if(ud->extra) pcre_free(ud->extra); - if(ud->tables) pcre_free((void *)ud->tables); - if(ud->match) free(ud->match); - } - return 0; -} - -static int Lpcre_tostring (lua_State *L) { - return udata_tostring(L, pcre_handle, pcre_typename); -} - -static int Lpcre_vers (lua_State *L) -{ - lua_pushstring(L, pcre_version()); - return 1; -} - -static flags_pair pcre_flags[] = -{ - { "CASELESS", PCRE_CASELESS }, - { "MULTILINE", PCRE_MULTILINE }, - { "DOTALL", PCRE_DOTALL }, - { "EXTENDED", PCRE_EXTENDED }, - { "ANCHORED", PCRE_ANCHORED }, - { "DOLLAR_ENDONLY", PCRE_DOLLAR_ENDONLY }, - { "EXTRA", PCRE_EXTRA }, - { "NOTBOL", PCRE_NOTBOL }, - { "NOTEOL", PCRE_NOTEOL }, - { "UNGREEDY", PCRE_UNGREEDY }, - { "NOTEMPTY", PCRE_NOTEMPTY }, - { "UTF8", PCRE_UTF8 }, -#if PCRE_MAJOR >= 4 - { "NO_AUTO_CAPTURE", PCRE_NO_AUTO_CAPTURE }, - { "NO_UTF8_CHECK", PCRE_NO_UTF8_CHECK }, -#endif -#ifdef PCRE_AUTO_CALLOUT - { "AUTO_CALLOUT", PCRE_AUTO_CALLOUT }, -#endif -#ifdef PCRE_PARTIAL - { "PARTIAL", PCRE_PARTIAL }, -#endif -#ifdef PCRE_DFA_SHORTEST - { "DFA_SHORTEST", PCRE_DFA_SHORTEST }, -#endif -#ifdef PCRE_DFA_RESTART - { "DFA_RESTART", PCRE_DFA_RESTART }, -#endif -#ifdef PCRE_FIRSTLINE - { "FIRSTLINE", PCRE_FIRSTLINE }, -#endif -#ifdef PCRE_DUPNAMES - { "DUPNAMES", PCRE_DUPNAMES }, -#endif -#ifdef PCRE_NEWLINE_CR - { "NEWLINE_CR", PCRE_NEWLINE_CR }, -#endif -#ifdef PCRE_NEWLINE_LF - { "NEWLINE_LF", PCRE_NEWLINE_LF }, -#endif -#ifdef PCRE_NEWLINE_CRLF - { "NEWLINE_CRLF", PCRE_NEWLINE_CRLF }, -#endif -#ifdef PCRE_NEWLINE_ANY - { "NEWLINE_ANY", PCRE_NEWLINE_ANY }, -#endif -#ifdef PCRE_NEWLINE_ANYCRLF - { "NEWLINE_ANYCRLF", PCRE_NEWLINE_ANYCRLF }, -#endif -#ifdef PCRE_BSR_ANYCRLF - { "BSR_ANYCRLF", PCRE_BSR_ANYCRLF }, -#endif -#ifdef PCRE_BSR_UNICODE - { "BSR_UNICODE", PCRE_BSR_UNICODE }, -#endif - { NULL, 0 } -}; - -static int Lpcre_get_flags (lua_State *L) { - return get_flags(L, pcre_flags); -} - -static const luaL_Reg pcremeta[] = { - {"exec", Lpcre_exec}, - {"match", Lpcre_match}, - {"gmatch", Lpcre_gmatch}, - {"__gc", Lpcre_gc}, - {"__tostring", Lpcre_tostring}, - {NULL, NULL} -}; - -/* Open the library */ -static const luaL_Reg pcrelib[] = { - {"new", Lpcre_comp}, - {"flags", Lpcre_get_flags}, - {"version", Lpcre_vers}, - {NULL, NULL} -}; - -LUALIB_API int luaopen_pcrelib(lua_State *L) -{ - luaL_newmetatable(L, pcre_handle); - lua_pushliteral(L, "__index"); - luaL_newlib(L, pcremeta); - lua_rawset(L, -3); - lua_pop(L, 1); - - luaL_newlib(L, pcrelib); - - return 1; -} diff --git a/nse_pcrelib.h b/nse_pcrelib.h deleted file mode 100644 index 512d2a8..0000000 --- a/nse_pcrelib.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef NSE_PCRELIB -#define NSE_PCRELIB - -#define NSE_PCRELIBNAME "pcre" - -LUALIB_API int luaopen_pcrelib (lua_State *L); - -#endif - diff --git a/nselib/pcre.luadoc b/nselib/pcre.luadoc deleted file mode 100644 index c442a96..0000000 --- a/nselib/pcre.luadoc +++ /dev/null @@ -1,135 +0,0 @@ ---- --- Perl Compatible Regular Expressions. --- --- One of Lua's quirks is its string patterns. While they have great performance --- and are tightly integrated into the Lua interpreter, they are very different --- in syntax and not as powerful as standard regular expressions. So we have --- integrated Perl compatible regular expressions into Lua using PCRE and a --- modified version of the Lua PCRE library written by Reuben Thomas and Shmuel --- Zeigerman. These are the same sort of regular expressions used by Nmap --- version detection. The main modification to their library is that the NSE --- version only supports PCRE expressions instead of both PCRE and POSIX --- patterns. In order to maintain a high script execution speed, the library --- interfacing with PCRE is kept very thin. It is not integrated as seamlessly --- as the Lua string pattern API. This allows script authors to decide when to --- use PCRE expressions versus Lua patterns. The use of PCRE involves a --- separate pattern compilation step, which saves execution time when patterns --- are reused. Compiled patterns can be cached in the NSE registry and reused --- by other scripts. --- --- The documentation for this module is derived from that supplied by the PCRE --- Lua lib. --- --- Warning: PCRE has a history of security vulnerabilities allowing attackers --- who are able to compile arbitrary regular expressions to execute arbitrary --- code. More such vulnerabilities may be discovered in the future. These have --- never affected Nmap because it doesn't give attackers any control over the --- regular expressions it uses. Similarly, NSE scripts should never build --- regular expressions with untrusted network input. Matching hardcoded regular --- expressions against the untrusted input is fine. --- @author Reuben Thomas --- @author Shmuel Zeigerman - -module "pcre" - ---- Returns a compiled regular expression. --- --- The resulting compiled regular expression is ready to be matched against --- strings. Compiled regular expressions are subject to Lua's garbage --- collection. --- --- The compilation flags are set bitwise. If you want to set the 3rd --- (corresponding to the number 4) and the 1st (corresponding to 1) bit for --- example you would pass the number 5 as a second argument. The compilation --- flags accepted are those of the PCRE C library. These include flags for case --- insensitive matching (<code>1</code>), matching line beginnings --- (<code>^</code>) and endings (<code>$</code>) even in multiline strings --- (i.e. strings containing newlines) (<code>2</code>) and a flag for matching --- across line boundaries (<code>4</code>). No compilation flags yield a --- default value of <code>0</code>. --- @param pattern a string describing the pattern, such as <code>"^foo$"</code>. --- @param flags a number describing which compilation flags are set. --- @param locale a string describing the locale which should be used to compile --- the regular expression (optional). The value is a string which is passed to --- the C standard library function <code>setlocale</code>. For more --- information on this argument refer to the documentation of --- <code>setlocale</code>. --- @usage local regex = pcre.new("pcre-pattern",0,"C") -function new(pattern, flags, locale) - ---- Returns a table of the available PCRE option flags (numbers) keyed by their --- names (strings). --- --- Possible names of the available strings can be retrieved from the --- documentation of the PCRE library used to link against Nmap. The key is the --- option name in the manual minus the <code>PCRE_</code> prefix. --- <code>PCRE_CASELESS</code> becomes <code>CASELESS</code> for example. -function flags() - ---- Returns the version of the PCRE library in use as a string. --- --- For example <code>"6.4 05-Sep-2005"</code>. -function version() - ---- Matches a string against a compiled regular expression. --- --- Returns the start point and the end point of the first match of the compiled --- regular expression in the string. --- @param string the string to match against. --- @param start where to start the match in the string (optional). --- @param flags execution flags (optional). --- @return <code>nil</code> if no match, otherwise the start point of the first --- match. --- @return the end point of the first match. --- @return a table which contains false in the positions where the pattern did --- not match. If named sub-patterns were used, the table also contains substring --- matches keyed by their sub-pattern name. --- @usage --- i, j = regex:match("string to be searched", 0, 0) --- if (i) then ... end -function match(string, start, flags) - ---- Matches a string against a compiled regular expression, returning positions --- of substring matches. --- --- This function is like <code>match</code> except that a table returned as a --- third result contains offsets of substring matches rather than substring --- matches themselves. That table will not contain string keys, even if named --- sub-patterns are used. For example, if the whole match is at offsets 10, 20 --- and substring matches are at offsets 12, 14 and 16, 19 then the function --- returns <code>10, 20, {12,14,16,19}</code>. --- @param string the string to match against. --- @param start where to start the match in the string (optional). --- @param flags execution flags (optional). --- @return <code>nil</code> if no match, otherwise the start point of the match --- of the whole string. --- @return the end point of the match of the whole string. --- @return a table containing a list of substring match start and end positions. --- @usage --- i, j, substrings = regex:exec("string to be searched", 0, 0) --- if (i) then ... end -function exec(string, start, flags) - ---- Matches a string against a regular expression multiple times. --- --- Tries to match the regular expression pcre_obj against string up to --- <code>n</code> times (or as many as possible if <code>n</code> is not given --- or is not a positive number), subject to the execution flags --- <code>ef</code>. Each time there is a match, <code>func</code> is called as --- <code>func(m, t)</code>, where <code>m</code> is the matched string and --- <code>t</code> is a table of substring matches. This table contains false in --- the positions where the corresponding sub-pattern did not match. If named --- sub-patterns are used then the table also contains substring matches keyed --- by their correspondent sub-pattern names (strings). If <code>func</code> --- returns a true value, then <code>gmatch</code> immediately returns; --- <code>gmatch</code> returns the number of matches made. --- @param string the string to match against. --- @param func the function to call for each match. --- @param n the maximum number of matches to do (optional). --- @param ef execution flags (optional). --- @return the number of matches made. --- @usage --- local t = {} --- local function match(m) t[#t + 1] = m end --- local n = regex:gmatch("string to be searched", match) -function pcre_obj:gmatch(string, func, n, ef) diff --git a/service_scan.cc b/service_scan.cc index cf13d8b..473b3a6 100644 --- a/service_scan.cc +++ b/service_scan.cc @@ -250,7 +250,7 @@ ServiceProbeMatch::ServiceProbeMatch() { product_template = version_template = info_template = NULL; hostname_template = ostype_template = devicetype_template = NULL; regex_compiled = NULL; - regex_extra = NULL; + match_data = NULL; isInitialized = false; matchops_ignorecase = false; matchops_dotall = false; @@ -269,8 +269,21 @@ ServiceProbeMatch::~ServiceProbeMatch() { if (devicetype_template) free(devicetype_template); for (it = cpe_templates.begin(); it != cpe_templates.end(); it++) free(*it); - if (regex_compiled) pcre_free(regex_compiled); - if (regex_extra) pcre_free(regex_extra); + if (regex_compiled) + { + pcre2_code_free(regex_compiled); + regex_compiled=NULL; + } + if (match_data) + { + pcre2_match_data_free(match_data); + match_data=NULL; + } + if (match_context) + { + pcre2_match_context_free(match_context); + match_context=NULL; + } isInitialized = false; } @@ -350,9 +363,9 @@ void ServiceProbeMatch::InitMatch(const char *matchtext, int lineno) { char *tmptemplate; char modestr[4]; char flags[4]; - int pcre_compile_ops = 0; - const char *pcre_errptr = NULL; - int pcre_erroffset = 0; + int pcre2_compile_ops = 0; + int pcre2_errcode; + PCRE2_SIZE pcre2_erroffset; char **curr_tmp = NULL; if (isInitialized) fatal("Sorry ... %s does not yet support reinitializion", __func__); @@ -405,41 +418,42 @@ void ServiceProbeMatch::InitMatch(const char *matchtext, int lineno) { // Next we compile and study the regular expression to match if (matchops_ignorecase) - pcre_compile_ops |= PCRE_CASELESS; + pcre2_compile_ops |= PCRE2_CASELESS; if (matchops_dotall) - pcre_compile_ops |= PCRE_DOTALL; + pcre2_compile_ops |= PCRE2_DOTALL; - regex_compiled = pcre_compile(matchstr, pcre_compile_ops, &pcre_errptr, - &pcre_erroffset, NULL); + regex_compiled = pcre2_compile((PCRE2_SPTR)matchstr,PCRE2_ZERO_TERMINATED, pcre2_compile_ops, &pcre2_errcode, + &pcre2_erroffset, NULL); if (regex_compiled == NULL) - fatal("%s: illegal regexp on line %d of nmap-service-probes (at regexp offset %d): %s\n", __func__, lineno, pcre_erroffset, pcre_errptr); + fatal("%s: illegal regexp on line %d of nmap-service-probes (at regexp offset %ld): %d\n", __func__, lineno, pcre2_erroffset, pcre2_errcode); - // Now study the regexp for greater efficiency - regex_extra = pcre_study(regex_compiled, 0 -#ifdef PCRE_STUDY_EXTRA_NEEDED - | PCRE_STUDY_EXTRA_NEEDED -#endif - , &pcre_errptr); - if (pcre_errptr != NULL) - fatal("%s: failed to pcre_study regexp on line %d of nmap-service-probes: %s\n", __func__, lineno, pcre_errptr); + // creates a new match data block for holding the result of a match + match_data = pcre2_match_data_create_from_pattern( + regex_compiled,NULL + ); - if (!regex_extra) { - regex_extra = (pcre_extra *) pcre_malloc(sizeof(pcre_extra)); - memset(regex_extra, 0, sizeof(pcre_extra)); + if (!match_data) { + fatal("%s: failed to allocate match_data\n", __func__); } + match_context = pcre2_match_context_create(NULL); + + if (!match_context) { + fatal("%s: failed to allocate match_context\n", __func__); + } // Set some limits to avoid evil match cases. // These are flexible; if they cause problems, increase them. -#ifdef PCRE_ERROR_MATCHLIMIT - regex_extra->match_limit = 100000; // 100K -#endif -#ifdef PCRE_ERROR_RECURSIONLIMIT - regex_extra->match_limit_recursion = 10000; // 10K + pcre2_set_match_limit(match_context, 100000); +#ifdef pcre2_set_depth_limit + // Changed name in PCRE2 10.30. PCRE2 uses macro definitions for function + // names, so we don't have to add this to configure.ac. + pcre2_set_depth_limit(match_context, 10000); +#else + pcre2_set_recursion_limit(match_context, 10000); #endif - /* OK! Now we look for any templates of the form ?/.../ * where ? is either p, v, i, h, o, or d. / is any * delimiter character and ... is a template */ @@ -509,34 +523,29 @@ const struct MatchDetails *ServiceProbeMatch::testMatch(const u8 *buf, int bufle static char devicetype[32]; static char cpe_a[80], cpe_h[80], cpe_o[80]; char *bufc = (char *) buf; - int ovector[150]; // allows 50 substring matches (including the overall match) assert(isInitialized); // Clear out the output struct memset(&MD_return, 0, sizeof(MD_return)); MD_return.isSoft = isSoft; - rc = pcre_exec(regex_compiled, regex_extra, bufc, buflen, 0, 0, ovector, sizeof(ovector) / sizeof(*ovector)); + rc = pcre2_match(regex_compiled, (PCRE2_SPTR8)bufc, buflen, 0, 0, match_data, match_context); if (rc < 0) { -#ifdef PCRE_ERROR_MATCHLIMIT // earlier PCRE versions lack this - if (rc == PCRE_ERROR_MATCHLIMIT) { + if (rc == PCRE2_ERROR_MATCHLIMIT) { if (o.debugging || o.verbose > 1) error("Warning: Hit PCRE_ERROR_MATCHLIMIT when probing for service %s with the regex '%s'", servicename, matchstr); } else -#endif // PCRE_ERROR_MATCHLIMIT -#ifdef PCRE_ERROR_RECURSIONLIMIT - if (rc == PCRE_ERROR_RECURSIONLIMIT) { + if (rc == PCRE2_ERROR_RECURSIONLIMIT) { if (o.debugging || o.verbose > 1) error("Warning: Hit PCRE_ERROR_RECURSIONLIMIT when probing for service %s with the regex '%s'", servicename, matchstr); } else -#endif // PCRE_ERROR_RECURSIONLIMIT - if (rc != PCRE_ERROR_NOMATCH) { + if (rc != PCRE2_ERROR_NOMATCH) { fatal("Unexpected PCRE error (%d) when probing for service %s with the regex '%s'", rc, servicename, matchstr); } } else { // Yeah! Match apparently succeeded. // Now lets get the version number if available - getVersionStr(buf, buflen, ovector, rc, product, sizeof(product), version, sizeof(version), info, sizeof(info), + getVersionStr(buf, buflen, product, sizeof(product), version, sizeof(version), info, sizeof(info), hostname, sizeof(hostname), ostype, sizeof(ostype), devicetype, sizeof(devicetype), cpe_a, sizeof(cpe_a), cpe_h, sizeof(cpe_h), cpe_o, sizeof(cpe_o)); if (*product) MD_return.product = product; @@ -685,18 +694,17 @@ static char *transform_cpe(const char *s) { // This function does the substitution of a placeholder like $2 or $P(4). It // returns a newly allocated string, or NULL if it fails. tmplvar is a template // variable, such as "$P(2)". We set *tmplvarend to the character after the -// variable. subject, subjectlen, ovector, and nummatches mean the same as in +// variable. subject, subjectlen, and match_data mean the same as in // dotmplsubst(). static char *substvar(char *tmplvar, char **tmplvarend, - const u8 *subject, int subjectlen, int *ovector, - int nummatches) { + const u8 *subject, size_t subjectlen, pcre2_match_data *match_data + ) { char substcommand[16]; char *p = NULL; char *p_end; - int subnum = 0; - int offstart, offend; + u8 subnum = 0; + PCRE2_SIZE offstart, offend; int rc; - int i; struct substargs command_args; char *result; size_t n, len; @@ -728,6 +736,8 @@ static char *substvar(char *tmplvar, char **tmplvarend, } if (tmplvarend) *tmplvarend = tmplvar; + u32 nummatches = pcre2_get_ovector_count(match_data); + PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data); strbuf_init(&result, &n, &len); if (!*substcommand) { @@ -735,9 +745,10 @@ static char *substvar(char *tmplvar, char **tmplvarend, if (subnum > 9 || subnum <= 0) return NULL; if (subnum >= nummatches) return NULL; offstart = ovector[subnum * 2]; + if (offstart == PCRE2_UNSET) return NULL; offend = ovector[subnum * 2 + 1]; - assert(offstart >= 0 && offstart <= subjectlen); - assert(offend >= 0 && offend <= subjectlen); + assert(offstart <= subjectlen); + assert(offend != PCRE2_UNSET && offend <= subjectlen); // A plain-jane copy strbuf_append(&result, &n, &len, (const char *) subject + offstart, offend - offstart); } else if (strcmp(substcommand, "P") == 0) { @@ -749,13 +760,14 @@ static char *substvar(char *tmplvar, char **tmplvarend, if (subnum > 9 || subnum <= 0) return NULL; if (subnum >= nummatches) return NULL; offstart = ovector[subnum * 2]; + if (offstart == PCRE2_UNSET) return NULL; offend = ovector[subnum * 2 + 1]; - assert(offstart >= 0 && offstart <= subjectlen); - assert(offend >= 0 && offend <= subjectlen); + assert(offstart <= subjectlen); + assert(offend != PCRE2_UNSET && offend <= subjectlen); // This filter only includes printable characters. It is particularly // useful for collapsing unicode text that looks like // "W\0O\0R\0K\0G\0R\0O\0U\0P\0" - for(i=offstart; i < offend; i++) { + for(PCRE2_SIZE i=offstart; i < offend; i++) { if (isprint((int) subject[i])) strbuf_append(&result, &n, &len, (const char *) subject + i, 1); } @@ -772,14 +784,15 @@ static char *substvar(char *tmplvar, char **tmplvarend, if (subnum > 9 || subnum <= 0) return NULL; if (subnum >= nummatches) return NULL; offstart = ovector[subnum * 2]; + if (offstart == PCRE2_UNSET) return NULL; offend = ovector[subnum * 2 + 1]; - assert(offstart >= 0 && offstart <= subjectlen); - assert(offend >= 0 && offend <= subjectlen); + assert(offstart <= subjectlen); + assert(offend != PCRE2_UNSET && offend <= subjectlen); findstr = command_args.str_args[1]; findstrlen = command_args.str_args_len[1]; replstr = command_args.str_args[2]; replstrlen = command_args.str_args_len[2]; - for(i=offstart; i < offend; ) { + for(PCRE2_SIZE i=offstart; i < offend; ) { if (memcmp(subject + i, findstr, findstrlen) != 0) { strbuf_append(&result, &n, &len, (const char *) subject + i, 1); // no match i++; @@ -805,8 +818,9 @@ static char *substvar(char *tmplvar, char **tmplvarend, if (subnum > 9 || subnum <= 0) return NULL; if (subnum >= nummatches) return NULL; offstart = ovector[subnum * 2]; + if (offstart == PCRE2_UNSET) return NULL; offend = ovector[subnum * 2 + 1]; - assert(offstart >= 0 && offstart <= subjectlen); + assert(offend != PCRE2_UNSET && offstart <= subjectlen); // overflow if (offend - offstart > 8) { @@ -824,11 +838,11 @@ static char *substvar(char *tmplvar, char **tmplvarend, break; } if (bigendian) { - for(i=offstart; i < offend; i++) { + for(PCRE2_SIZE i=offstart; i < offend; i++) { val = (val<<8) + subject[i]; } } else { - for(i=offend - 1; i > offstart - 1; i--) { + for(PCRE2_SIZE i=offend - 1; i > offstart - 1; i--) { val = (val<<8) + subject[i]; } } @@ -847,16 +861,16 @@ static char *substvar(char *tmplvar, char **tmplvarend, // This function takes a template string (tmpl) which can have // placeholders in it such as $1 for substring matches in a regexp -// that was run against subject, and subjectlen, with the 'nummatches' -// matches in ovector. The NUL-terminated newly composted string is +// that was run against subject, and subjectlen, with the +// matches in match_data. The NUL-terminated newly composted string is // placed into 'newstr', as long as it doesn't exceed 'newstrlen' // bytes. Trailing whitespace and commas are removed. Returns zero for success // // The transform argument is a function pointer. If not NULL, the given // function is applied to all substitutions before they are inserted // into the result string. -static int dotmplsubst(const u8 *subject, int subjectlen, - int *ovector, int nummatches, char *tmpl, char *newstr, +static int dotmplsubst(const u8 *subject, size_t subjectlen, + pcre2_match_data *match_data, char *tmpl, char *newstr, int newstrlen, char *(*transform)(const char *) = NULL) { int newlen; @@ -895,7 +909,7 @@ static int dotmplsubst(const u8 *subject, int subjectlen, dst += newlen; } srcstart = srcend; - subst = substvar(srcstart, &srcend, subject, subjectlen, ovector, nummatches); + subst = substvar(srcstart, &srcend, subject, subjectlen, match_data); if (subst == NULL) return -1; /* Apply transformation if requested. */ @@ -937,14 +951,14 @@ static int dotmplsubst(const u8 *subject, int subjectlen, // for a string, that string will have zero length after the function // call (assuming the corresponding length passed in is at least 1) -int ServiceProbeMatch::getVersionStr(const u8 *subject, int subjectlen, - int *ovector, int nummatches, char *product, int productlen, - char *version, int versionlen, char *info, int infolen, - char *hostname, int hostnamelen, char *ostype, int ostypelen, - char *devicetype, int devicetypelen, - char *cpe_a, int cpe_alen, - char *cpe_h, int cpe_hlen, - char *cpe_o, int cpe_olen) const { +int ServiceProbeMatch::getVersionStr(const u8 *subject, size_t subjectlen, + char *product, size_t productlen, + char *version, size_t versionlen, char *info, size_t infolen, + char *hostname, size_t hostnamelen, char *ostype, size_t ostypelen, + char *devicetype, size_t devicetypelen, + char *cpe_a, size_t cpe_alen, + char *cpe_h, size_t cpe_hlen, + char *cpe_o, size_t cpe_olen) const { int rc; assert(productlen >= 0 && versionlen >= 0 && infolen >= 0 && @@ -963,9 +977,9 @@ int ServiceProbeMatch::getVersionStr(const u8 *subject, int subjectlen, // Now lets get this started! We begin with the product name if (product_template) { - rc = dotmplsubst(subject, subjectlen, ovector, nummatches, product_template, product, productlen); + rc = dotmplsubst(subject, subjectlen, match_data, product_template, product, productlen); if (rc != 0) { - error("Warning: Servicescan failed to fill product_template (subjectlen: %d, productlen: %d). Capture exceeds length? Match string was line %d: p/%s/%s/%s", subjectlen, productlen, deflineno, + error("Warning: Servicescan failed to fill product_template (subjectlen: %lu, productlen: %lu). Capture exceeds length? Match string was line %d: p/%s/%s/%s", subjectlen, productlen, deflineno, (product_template)? product_template : "", (version_template)? version_template : "", (info_template)? info_template : ""); @@ -975,9 +989,9 @@ int ServiceProbeMatch::getVersionStr(const u8 *subject, int subjectlen, } if (version_template) { - rc = dotmplsubst(subject, subjectlen, ovector, nummatches, version_template, version, versionlen); + rc = dotmplsubst(subject, subjectlen, match_data, version_template, version, versionlen); if (rc != 0) { - error("Warning: Servicescan failed to fill version_template (subjectlen: %d, versionlen: %d). Capture exceeds length? Match string was line %d: v/%s/%s/%s", subjectlen, versionlen, deflineno, + error("Warning: Servicescan failed to fill version_template (subjectlen: %lu, versionlen: %lu). Capture exceeds length? Match string was line %d: v/%s/%s/%s", subjectlen, versionlen, deflineno, (product_template)? product_template : "", (version_template)? version_template : "", (info_template)? info_template : ""); @@ -987,9 +1001,9 @@ int ServiceProbeMatch::getVersionStr(const u8 *subject, int subjectlen, } if (info_template) { - rc = dotmplsubst(subject, subjectlen, ovector, nummatches, info_template, info, infolen); + rc = dotmplsubst(subject, subjectlen, match_data, info_template, info, infolen); if (rc != 0) { - error("Warning: Servicescan failed to fill info_template (subjectlen: %d, infolen: %d). Capture exceeds length? Match string was line %d: i/%s/%s/%s", subjectlen, infolen, deflineno, + error("Warning: Servicescan failed to fill info_template (subjectlen: %lu, infolen: %lu). Capture exceeds length? Match string was line %d: i/%s/%s/%s", subjectlen, infolen, deflineno, (product_template)? product_template : "", (version_template)? version_template : "", (info_template)? info_template : ""); @@ -999,9 +1013,9 @@ int ServiceProbeMatch::getVersionStr(const u8 *subject, int subjectlen, } if (hostname_template) { - rc = dotmplsubst(subject, subjectlen, ovector, nummatches, hostname_template, hostname, hostnamelen); + rc = dotmplsubst(subject, subjectlen, match_data, hostname_template, hostname, hostnamelen); if (rc != 0) { - error("Warning: Servicescan failed to fill hostname_template (subjectlen: %d, hostnamelen: %d). Capture exceeds length? Match string was line %d: h/%s/", subjectlen, hostnamelen, deflineno, + error("Warning: Servicescan failed to fill hostname_template (subjectlen: %lu, hostnamelen: %lu). Capture exceeds length? Match string was line %d: h/%s/", subjectlen, hostnamelen, deflineno, (hostname_template)? hostname_template : ""); if (hostnamelen > 0) *hostname = '\0'; retval = -1; @@ -1009,9 +1023,9 @@ int ServiceProbeMatch::getVersionStr(const u8 *subject, int subjectlen, } if (ostype_template) { - rc = dotmplsubst(subject, subjectlen, ovector, nummatches, ostype_template, ostype, ostypelen); + rc = dotmplsubst(subject, subjectlen, match_data, ostype_template, ostype, ostypelen); if (rc != 0) { - error("Warning: Servicescan failed to fill ostype_template (subjectlen: %d, ostypelen: %d). Capture exceeds length? Match string was line %d: o/%s/", subjectlen, ostypelen, deflineno, + error("Warning: Servicescan failed to fill ostype_template (subjectlen: %lu, ostypelen: %lu). Capture exceeds length? Match string was line %d: o/%s/", subjectlen, ostypelen, deflineno, (ostype_template)? ostype_template : ""); if (ostypelen > 0) *ostype = '\0'; retval = -1; @@ -1019,9 +1033,9 @@ int ServiceProbeMatch::getVersionStr(const u8 *subject, int subjectlen, } if (devicetype_template) { - rc = dotmplsubst(subject, subjectlen, ovector, nummatches, devicetype_template, devicetype, devicetypelen); + rc = dotmplsubst(subject, subjectlen, match_data, devicetype_template, devicetype, devicetypelen); if (rc != 0) { - error("Warning: Servicescan failed to fill devicetype_template (subjectlen: %d, devicetypelen: %d). Too long? Match string was line %d: d/%s/", subjectlen, devicetypelen, deflineno, + error("Warning: Servicescan failed to fill devicetype_template (subjectlen: %lu, devicetypelen: %lu). Too long? Match string was line %d: d/%s/", subjectlen, devicetypelen, deflineno, (devicetype_template)? devicetype_template : ""); if (devicetypelen > 0) *devicetype = '\0'; retval = -1; @@ -1032,7 +1046,7 @@ int ServiceProbeMatch::getVersionStr(const u8 *subject, int subjectlen, store in cpe_a, cpe_h, or cpe_o as appropriate. */ for (unsigned int i = 0; i < cpe_templates.size(); i++) { char *cpe; - int cpelen; + size_t cpelen; int part; part = cpe_get_part(cpe_templates[i]); @@ -1055,9 +1069,9 @@ int ServiceProbeMatch::getVersionStr(const u8 *subject, int subjectlen, continue; break; } - rc = dotmplsubst(subject, subjectlen, ovector, nummatches, cpe_templates[i], cpe, cpelen, transform_cpe); + rc = dotmplsubst(subject, subjectlen, match_data, cpe_templates[i], cpe, cpelen, transform_cpe); if (rc != 0) { - error("Warning: Servicescan failed to fill cpe_%c (subjectlen: %d, cpelen: %d). Too long? Match string was line %d: %s", part, subjectlen, cpelen, deflineno, + error("Warning: Servicescan failed to fill cpe_%c (subjectlen: %lu, cpelen: %lu). Too long? Match string was line %d: %s", part, subjectlen, cpelen, deflineno, (cpe_templates[i])? cpe_templates[i] : ""); if (cpelen > 0) *cpe = '\0'; retval = -1; diff --git a/service_scan.h b/service_scan.h index 7723d81..8ebdee7 100644 --- a/service_scan.h +++ b/service_scan.h @@ -69,16 +69,8 @@ #include <vector> -#ifdef HAVE_CONFIG_H -/* Needed for HAVE_PCRE_PCRE_H below */ -#include "nmap_config.h" -#endif /* HAVE_CONFIG_H */ - -#ifdef HAVE_PCRE_PCRE_H -# include <pcre/pcre.h> -#else -# include <pcre.h> -#endif +#define PCRE2_CODE_UNIT_WIDTH 8 +#include <pcre2.h> #undef NDEBUG #include <assert.h> @@ -155,8 +147,9 @@ class ServiceProbeMatch { bool isInitialized; // Has InitMatch yet been called? const char *servicename; char *matchstr; // Regular expression text - pcre *regex_compiled; - pcre_extra *regex_extra; + pcre2_code *regex_compiled; + pcre2_match_data *match_data; + pcre2_match_context *match_context; bool matchops_ignorecase; bool matchops_dotall; bool isSoft; // is this a soft match? ("softmatch" keyword in nmap-service-probes) @@ -179,14 +172,14 @@ class ServiceProbeMatch { // are sufficient). Returns zero for success. If no template is available // for a string, that string will have zero length after the function // call (assuming the corresponding length passed in is at least 1) - int getVersionStr(const u8 *subject, int subjectlen, int *ovector, - int nummatches, char *product, int productlen, - char *version, int versionlen, char *info, int infolen, - char *hostname, int hostnamelen, char *ostype, int ostypelen, - char *devicetype, int devicetypelen, - char *cpe_a, int cpe_alen, - char *cpe_h, int cpe_hlen, - char *cpe_o, int cpe_olen) const; + int getVersionStr(const u8 *subject, size_t subjectlen, + char *product, size_t productlen, + char *version, size_t versionlen, char *info, size_t infolen, + char *hostname, size_t hostnamelen, char *ostype, size_t ostypelen, + char *devicetype, size_t devicetypelen, + char *cpe_a, size_t cpe_alen, + char *cpe_h, size_t cpe_hlen, + char *cpe_o, size_t cpe_olen) const; };
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2