diff --git a/.gitignore b/.gitignore index cbd5ac14d..8f1637e04 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ stamp-h1 /nping/nping_config.h /nsock/include/nsock_config.h /nsock/tests/tests_main +/tests/*_test /zenmap/build/ /zenmap/INSTALLED_FILES TAGS diff --git a/Makefile.in b/Makefile.in index a92430124..681242a35 100644 --- a/Makefile.in +++ b/Makefile.in @@ -263,7 +263,7 @@ clean-nping: -cd $(NPINGDIR) && $(MAKE) clean clean-tests: - @rm -f tests/check_dns + @rm -f tests/nmap_dns_test tests/expr_match_test distclean-pcap: -cd $(LIBPCAPDIR) && $(MAKE) distclean @@ -350,8 +350,8 @@ $(NPINGDIR)/nping.h: nmap.h $(ZENMAPDIR)/zenmapCore/Version.py $(ZENMAPDIR)/share/zenmap/config/zenmap_version: nmap.h cd $(ZENMAPDIR) && $(PYTHON) install_scripts/utils/version_update.py "$(NMAP_VERSION)" -tests/check_dns: $(OBJS) - $(CXX) -o $@ $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $^ $(LIBS) tests/nmap_dns_test.cc +tests/%: tests/%.cc $(OBJS) + $(CXX) -o $@ $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) $< # By default distutils rewrites installed scripts to hardcode the # location of the Python interpreter they were built with (something @@ -458,10 +458,10 @@ check-nsock: check-zenmap: @cd $(ZENMAPDIR)/test && $(PYTHON) run_tests.py -check-dns: tests/check_dns - $< +check-nmap: tests/nmap_dns_test tests/expr_match_test + for test in $^; do ./$$test; done -check: @NCAT_CHECK@ @NSOCK_CHECK@ @ZENMAP_CHECK@ @NSE_CHECK@ @NDIFF_CHECK@ check-dns +check: @NCAT_CHECK@ @NSOCK_CHECK@ @ZENMAP_CHECK@ @NSE_CHECK@ @NDIFF_CHECK@ check-nmap ${srcdir}/configure: configure.ac cd ${srcdir} && autoconf diff --git a/osscan.cc b/osscan.cc index bfc751632..1b1612520 100644 --- a/osscan.cc +++ b/osscan.cc @@ -292,7 +292,7 @@ void FingerPrint::erase() { | (or) - (range) No parentheses are allowed. */ -static bool expr_match(const char *val, const char *expr) { +bool expr_match(const char *val, size_t vlenx, const char *expr, size_t explen, bool do_nested) { const char *p, *q, *q1; /* OHHHH YEEEAAAAAHHHH!#!@#$!% */ size_t vlen = strlen(val); @@ -366,7 +366,7 @@ static void AVal_match(const FingerTest &reference, const FingerTest &fprint, co fatal("%s: Got bogus point amount (%d) for test %s.%s", __func__, pointsThisTest, points.name.str, aDef.name.str); subtests += pointsThisTest; - if (expr_match(current_fp, current_ref)) { + if (expr_match(current_fp, 0, current_ref, 0)) { subtests_succeeded += pointsThisTest; } else { if (verbose) diff --git a/osscan.h b/osscan.h index 76f0fd717..775ab5150 100644 --- a/osscan.h +++ b/osscan.h @@ -319,5 +319,7 @@ const char *mergeFPs(FingerPrint *FPs[], int numFPs, bool isGoodFP, const u8 *mac, int openTcpPort, int closedTcpPort, int closedUdpPort, bool wrapit); +// Internal matching function. Defined here for test purposes. +bool expr_match(const char *val, size_t vlen, const char *expr, size_t explen, bool do_nested=false); #endif /*OSSCAN_H*/ diff --git a/tests/expr_match_test.cc b/tests/expr_match_test.cc new file mode 100644 index 000000000..390914080 --- /dev/null +++ b/tests/expr_match_test.cc @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include "../osscan.h" + +struct expr_test { + const char *expr; + const char *val; + bool result; +}; +const struct expr_test tests[] = { + {"M123", "M123", true}, + {"M123", "M120", false}, + {"M123", "0M123", false}, + {"M123", "M1234", false}, + {"A", "A", true}, + {"12345678", "12345678", true}, + {"123456780", "123456789", false}, + {"123456780", "123456780", true}, + {"123456780", "12345678001", false}, + {">A", "B", true}, + {">B", "A", false}, + {">B0", "C0", true}, + {">C0", "C0", false}, + {">C0", "B0", false}, + {">B0", "100", true}, + {"10", "B00", true}, + {"<10", "1", true}, + {"<10", "9", true}, + {"A|B", "B", true}, + {"5-B", "B", true}, + {"5-B", "5", true}, + {"5-B", "6", true}, + {"5-B", "A", true}, + {"5-B", "4", false}, + {"5-B", "C", false}, + {"5-B", "51", false}, + {"5-B", "B2", false}, + {"5-B", "32", false}, + {"5-B", "9B", false}, + {"M123|B", "B", true}, + {"M123|B", "M123", true}, + {"B|M123", "B", true}, + {"B|M123", "M123", true}, + {"A", "", false}, + {"1-9", "", false}, +#if 0 + {"M[1-9]", "M2", true}, + {"M[<5]S", "M2S", true}, + {"M[>A]S", "MFS", true}, + {"M[>A7]S", "MA9S", true}, + {"M[>A7]S", "M111S", true}, + {"M[1]S", "M1S", true}, + {"M[1|A]S", "M1S", true}, + {"M[1|A]S", "MAS", true}, + {"M[1-9]", "MA", false}, + {"M[<5]S", "M9S", false}, + {"M[>A]S", "M2S", false}, + {"M[1]S", "M3S", false}, + {"M[1|A]S", "M1AS", false}, + {"M[1|A]S", "M9S", false}, + {"M[1-9]", "M2A", false}, + {"M[1-9]", "M2T", false}, + {"M[<5]S", "M2BS", false}, + {"M[<5]S", "M2B", false}, + {"M[>A7]S", "MFS", false}, + {"M[>A7]S", "MA6S", false}, + {"[1-9]", "2", true}, + {"[<5]S", "2S", true}, + {"[>A]S", "FS", true}, + {"[>A7]S", "A9S", true}, + {"[>A7]S", "111S", true}, + {"[1]S", "1S", true}, + {"[1|A]S", "1S", true}, + {"[1|A]S", "AS", true}, + {"[1-9]", "A", false}, + {"[<5]S", "9S", false}, + {"[>A]S", "2S", false}, + {"[1]S", "3S", false}, + {"[1|A]S", "1AS", false}, + {"[1|A]S", "9S", false}, + {"[1-9]", "2A", false}, + {"[1-9]", "2T", false}, + {"[<5]S", "2BS", false}, + {"[<5]S", "2B", false}, + {"[>A7]S", "FS", false}, + {"[>A7]S", "A6S", false}, +#endif + {"", "", true} +}; + +int main(int argc, char **argv) +{ + size_t num_tests = sizeof(tests) / sizeof(expr_test); + size_t num_fail = 0; + for (size_t i=0; i < num_tests; i++) { + const char *val = tests[i].val; + const char *expr = tests[i].expr; + bool expected = tests[i].result; + std::cout << i << '\r'; + if (expected != expr_match(val, 0, expr, 0, strchr(expr, '['))) { + std::cout << "FAIL test " << i << ": " << val << + (expected ? " nomatch " : " badmatch ") << expr << std::endl; + num_fail++; + } + } + std::cout << "Ran " << num_tests << " tests. " << num_fail << " failures." << std::endl; + return num_fail; +}