From 3bc8ffe276d13346b51a2d07ebcbeffefdd7bf1a Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 26 May 2026 20:53:50 +0100 Subject: [PATCH] regexp: update pcre2 for type safety --- src/util/regexp.c | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/src/util/regexp.c b/src/util/regexp.c index 84d5b607c..ca0d043ec 100644 --- a/src/util/regexp.c +++ b/src/util/regexp.c @@ -84,8 +84,9 @@ int git_regexp_compile(git_regexp *r, const char *pattern, int flags) if (flags & GIT_REGEXP_ICASE) cflags |= PCRE2_CASELESS; - if ((*r = pcre2_compile((const unsigned char *) pattern, PCRE2_ZERO_TERMINATED, - cflags, &error, &erroff, NULL)) == NULL) { + if ((*r = pcre2_compile((const unsigned char *) pattern, + PCRE2_ZERO_TERMINATED, + cflags, &error, &erroff, NULL)) == NULL) { pcre2_get_error_message(error, errmsg, sizeof(errmsg)); git_error_set_str(GIT_ERROR_REGEX, (char *) errmsg); return GIT_EINVALIDSPEC; @@ -110,37 +111,51 @@ int git_regexp_match(const git_regexp *r, const char *string) error = pcre2_match(*r, (const unsigned char *) string, strlen(string), 0, 0, data, NULL); pcre2_match_data_free(data); + if (error < 0) return (error == PCRE2_ERROR_NOMATCH) ? GIT_ENOTFOUND : GIT_EINVALIDSPEC; return 0; } -int git_regexp_search(const git_regexp *r, const char *string, size_t nmatches, git_regmatch *matches) +int git_regexp_search( + const git_regexp *r, + const char *string, + size_t given_nmatches, + git_regmatch *matches) { pcre2_match_data *data = NULL; PCRE2_SIZE *ovec; + size_t i, captures; + uint32_t nmatches; int error; - size_t i; + + GIT_ASSERT(given_nmatches <= UINT32_MAX); + + nmatches = (uint32_t) given_nmatches; if ((data = pcre2_match_data_create(nmatches, NULL)) == NULL) { git_error_set_oom(); return -1; } - if ((error = pcre2_match(*r, (const unsigned char *) string, strlen(string), - 0, 0, data, NULL)) < 0) + if ((error = pcre2_match(*r, (const unsigned char *) string, + strlen(string), 0, 0, data, NULL)) < 0) goto out; - if (error == 0 || (unsigned int) error > nmatches) - error = nmatches; + captures = (size_t) error; + + if (!captures || captures > nmatches) + captures = nmatches; + ovec = pcre2_get_ovector_pointer(data); - for (i = 0; i < (unsigned int) error; i++) { + for (i = 0; i < captures; i++) { matches[i].start = (ovec[i * 2] == PCRE2_UNSET) ? -1 : (ssize_t) ovec[i * 2]; matches[i].end = (ovec[i * 2 + 1] == PCRE2_UNSET) ? -1 : (ssize_t) ovec[i * 2 + 1]; } - for (i = (unsigned int) error; i < nmatches; i++) + + for (i = captures; i < nmatches; i++) matches[i].start = matches[i].end = -1; out: