diff --git a/osscan.cc b/osscan.cc index ccdf50863..1e139aef2 100644 --- a/osscan.cc +++ b/osscan.cc @@ -301,10 +301,7 @@ bool expr_match(const char *val, size_t vlen, const char *expr, size_t explen, b explen = strlen(expr); // If both are empty, match; else if either is empty, no match. - if (vlen == 0) { - return explen == 0; - } - else if (explen == 0) { + if (explen == 0) { return vlen == 0; } @@ -318,6 +315,20 @@ bool expr_match(const char *val, size_t vlen, const char *expr, size_t explen, b q = strchr_p(p, p_end, '|'); nest = strchr_p(p, q ? q : p_end, '['); + if (vlen == 0) { + // value is empty, so can only match an empty expression + if (q == p || p == p_end ) { + // expression is also empty, match + return true; + } + else if (!nest) { + // simple expression before '|', no match. + goto next_expr; + } + // other short-circuit may be possible here, but drop to nesting logic + // below to avoid confusion/bugs + } + // if we're already in a nested expr, we skip this and just match as usual. if (do_nested && nest) { // As long as we keep finding nested portions, e.g. M[>500]ST11W[1-5] diff --git a/tests/expr_match_test.cc b/tests/expr_match_test.cc index 142037536..ce3d9fc2a 100644 --- a/tests/expr_match_test.cc +++ b/tests/expr_match_test.cc @@ -182,6 +182,14 @@ const struct expr_test tests[] = { {"001", "A", false}, {"0001", "A", false}, {"M5B4NNSNW5|M5B4NNSNW7|M5B4NNSNWA", "M5B4NNSNW7", true}, + {"|U", "U", true}, + {"|U", "", true}, + {"|1", "1", true}, + {"|1", "", true}, + {"U|", "U", true}, + {"U|", "", true}, + {"1|", "1", true}, + {"1|", "", true}, {"", "", true} };