https://github.com/nicm/fdm/commit/f1ec1982725d60045c0d871f3e613f2880046c22 From f1ec1982725d60045c0d871f3e613f2880046c22 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Wed, 1 Feb 2023 15:31:30 +0000 Subject: [PATCH] Fix bugs in PCRE2 code - don't walk off the end of the match list if NOMATCH is returned, and don't stop on empty matches. From Thomas Hurst. --- pcre.c | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/pcre.c b/pcre.c index e9a7f84..8d53532 100644 --- a/pcre.c +++ b/pcre.c @@ -66,7 +66,7 @@ int re_block(struct re *re, const void *buf, size_t len, struct rmlist *rml, char **cause) { - int res; + int res, ret; pcre2_match_data *pmd; PCRE2_SIZE *ovector; u_int i, j; @@ -85,27 +85,34 @@ re_block(struct re *re, const void *buf, size_t len, struct rmlist *rml, } pmd = pcre2_match_data_create_from_pattern(re->pcre2, NULL); - res = pcre2_match(re->pcre2, buf, len, 0, 0, pmd, NULL); - if (res < 0 && res != PCRE2_ERROR_NOMATCH) { - xasprintf(cause, "%s: regexec failed", re->str); - pcre2_match_data_free(pmd); - return (-1); - } + if (pmd == NULL) + fatalx("pcre2_match_data_create_from_pattern failed"); - if (rml != NULL) { - ovector = pcre2_get_ovector_pointer(pmd); - for (i = 0; i < res; i++) { - j = i * 2; - if (ovector[j + 1] <= ovector[j]) - break; - rml->list[i].valid = 1; - rml->list[i].so = ovector[j]; - rml->list[i].eo = ovector[j + 1]; + res = pcre2_match(re->pcre2, buf, len, 0, 0, pmd, NULL); + if (res > 0) { + if (rml != NULL) { + if (res > NPMATCH) + res = NPMATCH; + ovector = pcre2_get_ovector_pointer(pmd); + for (i = 0; i < res; i++) { + j = i * 2; + if (ovector[j + 1] < ovector[j]) + break; + rml->list[i].valid = 1; + rml->list[i].so = ovector[j]; + rml->list[i].eo = ovector[j + 1]; + } + rml->valid = 1; } - rml->valid = 1; + ret = 1; + } else if (res == PCRE2_ERROR_NOMATCH) + ret = 0; + else { + xasprintf(cause, "%s: regexec failed", re->str); + ret = -1; } - - return (res != PCRE2_ERROR_NOMATCH); + pcre2_match_data_free(pmd); + return (ret); } void