diff --git a/nmap-pcre2.patch b/nmap-pcre2.patch new file mode 100644 index 0000000..98ecc9b --- /dev/null +++ b/nmap-pcre2.patch @@ -0,0 +1,659 @@ +From 828ab48764b82d0226e860c73c5dac5b11f77385 Mon Sep 17 00:00:00 2001 +From: dmiller +Date: Sat, 24 Jun 2023 01:53:07 +0000 +Subject: [PATCH] Upgrade libpcre to PCRE2 10.42. Windows/macOS builds not + completed. + +--- +Backported to 7.93, excluded changes to unused bundled libpcre + + checklibs.sh | 10 +- + configure | 106 +++++++++------------------- + configure.ac | 23 +++--- + nmap.cc | 6 + + nmap_config.h.in | 2 + nping/nping_config.h.in | 2 + service_scan.cc | 180 +++++++++++++++++++++++++----------------------- + service_scan.h | 33 +++----- + 8 files changed, 168 insertions(+), 194 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 075df5cf5d..10a6034286 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -514,7 +514,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) +@@ -532,27 +532,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 d38821ad81..630d43bd70 100644 +--- a/nmap.cc ++++ b/nmap.cc +@@ -2786,10 +2786,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 79ec4e7620..5f6f32583b 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 98638cb410..9b6f97134d 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/service_scan.cc b/service_scan.cc +index f7de2ea8ce..7d99e5fbe4 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 @@ void ServiceProbeMatch::InitMatch(const char *matchtext, int lineno) { + 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,36 +517,31 @@ 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); + + assert (matchtype == SERVICEMATCH_REGEX); + + // 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; +@@ -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 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; +@@ -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 = 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) { +@@ -744,13 +756,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); + } +@@ -767,14 +780,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++; +@@ -800,8 +814,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) { +@@ -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) + 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]; + } + } +@@ -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_templates[i]); +@@ -1050,9 +1065,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 b17e3d2420..0ff168b6fc 100644 +--- a/service_scan.h ++++ b/service_scan.h +@@ -71,16 +71,8 @@ + + #include + +-#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 +-#else +-# include +-#endif ++#define PCRE2_CODE_UNIT_WIDTH 8 ++#include + + #undef NDEBUG + #include +@@ -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; + }; + + +From d131a096a869195be36ef7d4fa36739373346cb2 Mon Sep 17 00:00:00 2001 +From: dmiller +Date: Sat, 24 Jun 2023 01:53:09 +0000 +Subject: [PATCH] Remove nse_pcrelib from build. + +--- +Backported to 7.93 + + Makefile.in | 6 +++--- + nse_main.cc | 2 -- + nse_main.lua | 2 +- + nselib/unittest.lua | 1 - + 4 files changed, 4 insertions(+), 7 deletions(-) + +diff --git a/Makefile.in b/Makefile.in +index 2b13e866e7..a924301240 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 d5d460e6d4..2382688bd7 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 24c9d2ae7e..596aba9ba0 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 c3043fbc0b..c4e593f0ad 100644 +--- a/nselib/unittest.lua ++++ b/nselib/unittest.lua +@@ -107,7 +107,6 @@ local libs = { + "ospf", + "outlib", + "packet", +-"pcre", + "pgsql", + "pop3", + "pppoe", + diff --git a/nmap.spec b/nmap.spec index 867570c..ab344a7 100644 --- a/nmap.spec +++ b/nmap.spec @@ -7,7 +7,7 @@ Name: nmap Epoch: 3 Version: 7.93 #global prerelease TEST5 -Release: 3%{?dist} +Release: 4%{?dist} Summary: Network exploration tool and security scanner URL: http://nmap.org/ # Uses combination of licenses based on GPL license, but with extra modification @@ -30,6 +30,8 @@ Patch3: ncat_reg_stdin.diff Patch4: nmap-6.25-displayerror.patch # https://github.com/nmap/nmap/pull/2247 Patch7: nmap_resolve_config.patch +# backport of upstream pcre2 migration, rhbz#2128336 +Patch8: nmap-pcre2.patch BuildRequires: automake make @@ -43,7 +45,7 @@ BuildRequires: libssh2-devel BuildRequires: libtool BuildRequires: lua-devel BuildRequires: openssl-devel -BuildRequires: pcre-devel +BuildRequires: pcre2-devel BuildRequires: zlib-devel BuildRequires: gnupg2 Requires: %{name}-ncat = %{epoch}:%{version}-%{release} @@ -86,6 +88,7 @@ uses. %prep %{gpgverify} --keyring=%{SOURCE2} --signature='%{SOURCE1}' --data='%{SOURCE0}' %autosetup -p1 +autoconf -f #be sure we're not using tarballed copies of some libraries @@ -153,6 +156,9 @@ fi %{_mandir}/man1/ncat.1.gz %changelog +* Fri Nov 17 2023 Yaakov Selkowitz - 3:7.93-4 +- Use pcre2 instead of deprecated pcre (rhbz#2128336) + * Thu Jul 20 2023 Fedora Release Engineering - 3:7.93-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild