Projects
openEuler:Mainline
nmap
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 7
View file
_service:tar_scm:nmap.spec
Changed
@@ -3,22 +3,24 @@ Name: nmap Epoch: 2 Version: 7.92 -Release: 4 +Release: 5 License: Nmap Summary: A tool for network discovery and security auditing. Requires: %{name}-ncat = %{epoch}:%{version}-%{release} URL: https://nmap.org/ Source0: https://nmap.org/dist/%{name}-%{version}.tar.bz2 BuildRequires: automake autoconf gcc-c++ gettext-devel libpcap-devel libssh2-devel -BuildRequires: libtool lua-devel openssl-devel +BuildRequires: libtool lua-devel openssl-devel pcre2-devel Obsoletes: nmap-frontend nmap-ndiff nmap-ncat nc < 1.109.20120711-2 Obsoletes: nc6 < 1.00-22 Provides: nmap-frontend nmap-ndiff nmap-ncat nc nc6 -Patch0001: backport-nmap-4.03-mktemp.patch -Patch0002: backport-nmap_resolve_config.patch -Patch0003: nmap-replace-sensitive-words.patch +Patch0001: backport-nmap-4.03-mktemp.patch +Patch0002: backport-nmap_resolve_config.patch +Patch0003: nmap-replace-sensitive-words.patch +Patch0004: backport-upgrade-libpcre-to-PCRE2-10.42.patch +Patch0005: backport-remove-nse_pcrelib-from-build.patch %define pixmap_srcdir zenmap/share/pixmaps @@ -66,6 +68,12 @@ %{_mandir}/man1/*.1.gz %changelog +* Thu Jul 06 2023 xingwei <xingwei14@h-partners.com> - 2:7.92-5 +- Type:bugfix +- CVE: +- SUG:NA +- DESC:add pcre2 support + * Mon May 29 2023 xingwei <xingwei14@h-partners.com> - 2:7.92-4 - Type:bugfix - CVE:
View file
_service:tar_scm:backport-remove-nse_pcrelib-from-build.patch
Added
@@ -0,0 +1,80 @@ +From d131a096a869195be36ef7d4fa36739373346cb2 Mon Sep 17 00:00:00 2001 +From: dmiller <dmiller@e0a8ed71-7df4-0310-8962-fdc924857419> +Date: Sat, 24 Jun 2023 01:53:09 +0000 +Subject: PATCH Remove nse_pcrelib from build. + +Conflict: NA +Reference: https://github.com/nmap/nmap/commit/d131a096a869195be36ef7d4fa36739373346cb2 +--- + Makefile.in | 6 +++--- + mswin32/nmap.vcxproj | 2 -- + nse_main.cc | 2 -- + nse_main.lua | 2 +- + nselib/unittest.lua | 1 - + 5 files changed, 4 insertions(+), 9 deletions(-) + +diff --git a/Makefile.in b/Makefile.in +index ccfceda..8c19056 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -88,9 +88,9 @@ UNINSTALLNDIFF=@UNINSTALLNDIFF@ + UNINSTALLNPING=@UNINSTALLNPING@ + + ifneq (@NOLUA@,yes) +-NSE_SRC=nse_main.cc nse_utility.cc nse_nsock.cc nse_dnet.cc nse_fs.cc nse_nmaplib.cc nse_debug.cc nse_pcrelib.cc nse_lpeg.cc +-NSE_HDRS=nse_main.h nse_utility.h nse_nsock.h nse_dnet.h nse_fs.h nse_nmaplib.h nse_debug.h nse_pcrelib.h nse_lpeg.h +-NSE_OBJS=nse_main.o nse_utility.o nse_nsock.o nse_dnet.o nse_fs.o nse_nmaplib.o nse_debug.o nse_pcrelib.o nse_lpeg.o ++NSE_SRC=nse_main.cc nse_utility.cc nse_nsock.cc nse_dnet.cc nse_fs.cc nse_nmaplib.cc nse_debug.cc nse_lpeg.cc ++NSE_HDRS=nse_main.h nse_utility.h nse_nsock.h nse_dnet.h nse_fs.h nse_nmaplib.h nse_debug.h nse_lpeg.h ++NSE_OBJS=nse_main.o nse_utility.o nse_nsock.o nse_dnet.o nse_fs.o nse_nmaplib.o nse_debug.o nse_lpeg.o + ifneq (@OPENSSL_LIBS@,) + NSE_SRC+=nse_openssl.cc nse_ssl_cert.cc + NSE_HDRS+=nse_openssl.h nse_ssl_cert.h +diff --git a/nse_main.cc b/nse_main.cc +index 110291f..b946c7c 100644 +--- a/nse_main.cc ++++ b/nse_main.cc +@@ -14,7 +14,6 @@ + #include "nse_fs.h" + #include "nse_nsock.h" + #include "nse_nmaplib.h" +-#include "nse_pcrelib.h" + #include "nse_openssl.h" + #include "nse_debug.h" + #include "nse_lpeg.h" +@@ -557,7 +556,6 @@ static int panic (lua_State *L) + static void set_nmap_libraries (lua_State *L) + { + static const luaL_Reg libs = { +- {NSE_PCRELIBNAME, luaopen_pcrelib}, + {NSE_NMAPLIBNAME, luaopen_nmap}, + {LFSLIBNAME, luaopen_lfs}, + {LPEGLIBNAME, luaopen_lpeg}, +diff --git a/nse_main.lua b/nse_main.lua +index af5f611..7fba46e 100644 +--- a/nse_main.lua ++++ b/nse_main.lua +@@ -285,7 +285,7 @@ local REQUIRE_ERROR = {}; + rawset(stdnse, "silent_require", function (...) + local status, mod = pcall(require, ...); + if not status then +- print_debug(1, "%s", traceback(mod)); ++ print_debug(2, "%s", traceback(mod)); + error(REQUIRE_ERROR) + else + return mod; +diff --git a/nselib/unittest.lua b/nselib/unittest.lua +index ac90c31..d780b85 100644 +--- a/nselib/unittest.lua ++++ b/nselib/unittest.lua +@@ -107,7 +107,6 @@ local libs = { + "ospf", + "outlib", + "packet", +-"pcre", + "pgsql", + "pop3", + "pppoe", +-- +2.33.0 +
View file
_service:tar_scm:backport-upgrade-libpcre-to-PCRE2-10.42.patch
Added
@@ -0,0 +1,1336 @@ +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 ff58326..6483358 100644 +--- a/checklibs.sh ++++ b/checklibs.sh +@@ -11,13 +11,13 @@ trim_version() { + } + + check_libpcre() { +- PCRE_SOURCE="ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/" ++ 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 -ls $PCRE_SOURCE | perl -lne 'if(/pcre-(\d+.\d+).tar.gz$/){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 f8e1358..26cb1f6 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 +@@ -6421,58 +6421,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. */ + +@@ -6482,35 +6443,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 + + +@@ -6520,8 +6476,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" +@@ -6530,19 +6486,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 ac123af..6e695f3 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -507,7 +507,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) +@@ -525,27 +525,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 f1b8bf9..62984a5 100644 +--- a/nmap.cc ++++ b/nmap.cc +@@ -2764,10 +2764,12 @@ static void display_nmap_version() { + without.push_back("libz"); + #endif + ++ char pcre2_version255; ++ 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 c9ac750..10fdda9 100644 +--- a/nmap_config.h.in ++++ b/nmap_config.h.in +@@ -105,8 +105,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 9d4ccb4..2e4377f 100644 +--- a/nping/nping_config.h.in ++++ b/nping/nping_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/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 buf256; +- 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_locale256; +- 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 buf256; +- 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 (matchj >= 0) +- lua_pushlstring(L, text + matchj, (size_t)(matchj + 1 - matchj)); +- 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 = (tabptr0 << 8) | tabptr1; /* 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 (matchj >= 0) +- lua_pushlstring(L, text + matchj, matchj + 1 - matchj); +- 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->matchk >= 0) { +- lua_pushinteger(L, ud->matchk + 1); +- lua_rawseti(L, -2, j++); +- lua_pushinteger(L, ud->matchk+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->match0 + 1); +- lua_pushinteger(L, (lua_Number) ud->match1); +- (*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->match0, ud->match1 - ud->match0); +- Lpcre_push_substrings(L, text, ud); +- lua_call(L, 2, 1); +- if(lua_toboolean(L, -1)) +- break; +- lua_pop(L, 1); +- startoffset = ud->match1; +- } 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 66e0d92..8b57d9a 100644 +--- a/service_scan.cc ++++ b/service_scan.cc +@@ -247,7 +247,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; +@@ -268,8 +268,21 @@ ServiceProbeMatch::~ServiceProbeMatch() { + for (it = cpe_templates.begin(); it != cpe_templates.end(); it++) + free(*it); + matchstrlen = 0; +- 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; + matchops_anchor = -1; + } +@@ -347,9 +360,9 @@ static bool next_template(const char **matchtext, char **modestr, char **tmplt, + void ServiceProbeMatch::InitMatch(const char *matchtext, int lineno) { + const char *p; + char *modestr, *tmptemplate, *flags; +- 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,38 +418,40 @@ 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 + + free(modestr); +@@ -502,7 +517,6 @@ const struct MatchDetails *ServiceProbeMatch::testMatch(const u8 *buf, int bufle + static char devicetype32; + static char cpe_a80, cpe_h80, cpe_o80; + char *bufc = (char *) buf; +- int ovector150; // allows 50 substring matches (including the overall match) + assert(isInitialized); + + assert (matchtype == SERVICEMATCH_REGEX); +@@ -511,27 +525,23 @@ const struct MatchDetails *ServiceProbeMatch::testMatch(const u8 *buf, int bufle + 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; +@@ -680,18 +690,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 substcommand16; + 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; +@@ -723,6 +732,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) { +@@ -730,9 +741,10 @@ static char *substvar(char *tmplvar, char **tmplvarend, + if (subnum > 9 || subnum <= 0) return NULL; + if (subnum >= nummatches) return NULL; + offstart = ovectorsubnum * 2; ++ if (offstart == PCRE2_UNSET) return NULL; + offend = ovectorsubnum * 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) { +@@ -744,13 +756,14 @@ static char *substvar(char *tmplvar, char **tmplvarend, + if (subnum > 9 || subnum <= 0) return NULL; + if (subnum >= nummatches) return NULL; + offstart = ovectorsubnum * 2; ++ if (offstart == PCRE2_UNSET) return NULL; + offend = ovectorsubnum * 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) subjecti)) + strbuf_append(&result, &n, &len, (const char *) subject + i, 1); + } +@@ -767,14 +780,15 @@ static char *substvar(char *tmplvar, char **tmplvarend, + if (subnum > 9 || subnum <= 0) return NULL; + if (subnum >= nummatches) return NULL; + offstart = ovectorsubnum * 2; ++ if (offstart == PCRE2_UNSET) return NULL; + offend = ovectorsubnum * 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_args1; + findstrlen = command_args.str_args_len1; + replstr = command_args.str_args2; + replstrlen = command_args.str_args_len2; +- 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++; +@@ -800,8 +814,9 @@ static char *substvar(char *tmplvar, char **tmplvarend, + if (subnum > 9 || subnum <= 0) return NULL; + if (subnum >= nummatches) return NULL; + offstart = ovectorsubnum * 2; ++ if (offstart == PCRE2_UNSET) return NULL; + offend = ovectorsubnum * 2 + 1; +- assert(offstart >= 0 && offstart <= subjectlen); ++ assert(offend != PCRE2_UNSET && offstart <= subjectlen); + + // overflow + if (offend - offstart > 8) { +@@ -819,11 +834,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) + subjecti; + } + } else { +- for(i=offend - 1; i > offstart - 1; i--) { ++ for(PCRE2_SIZE i=offend - 1; i > offstart - 1; i--) { + val = (val<<8) + subjecti; + } + } +@@ -842,16 +857,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; +@@ -890,7 +905,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. */ +@@ -932,14 +947,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 && +@@ -958,9 +973,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 : ""); +@@ -970,9 +985,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 : ""); +@@ -982,9 +997,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 : ""); +@@ -994,9 +1009,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; +@@ -1004,9 +1019,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; +@@ -1014,9 +1029,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; +@@ -1027,7 +1042,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_templatesi); +@@ -1050,9 +1065,9 @@ int ServiceProbeMatch::getVersionStr(const u8 *subject, int subjectlen, + continue; + break; + } +- rc = dotmplsubst(subject, subjectlen, ovector, nummatches, cpe_templatesi, cpe, cpelen, transform_cpe); ++ rc = dotmplsubst(subject, subjectlen, match_data, cpe_templatesi, 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_templatesi)? cpe_templatesi : ""); + if (cpelen > 0) *cpe = '\0'; + retval = -1; +diff --git a/service_scan.h b/service_scan.h +index de2dfad..650a891 100644 +--- a/service_scan.h ++++ b/service_scan.h +@@ -71,16 +71,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> +@@ -162,8 +154,9 @@ class ServiceProbeMatch { + int matchtype; // SERVICEMATCH_REGEX or SERVICESCAN_STATIC + char *matchstr; // Regular expression text, or static string + int matchstrlen; // Because static strings may have embedded NULs +- 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) +@@ -189,14 +182,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; + }; + + +-- +2.33.0 +
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