[PATCH v4 2/3] regex: add regexec_buf() that can work on a non NUL-terminated string
- From
Johannes Schindelin <johannes.schindelin@gmx.de>
- Date
- Sep 21, 2016, 18:24 UTC
- Message-ID
- <270cea11c4d8bfb332a6c014a11673b7f4666ee4.1474482164.git.johannes.schindelin@gmx.de>
- In-Reply-To
- <cover.1474482164.git.johannes.schindelin@gmx.de>
We just introduced a test that demonstrates that our sloppy use of regexec() on a mmap()ed area can result in incorrect results or even hard crashes.
So what we need to fix this is a function that calls regexec() on a length-delimited, rather than a NUL-terminated, string.
Happily, there is an extension to regexec() introduced by the NetBSD project and present in all major regex implementation including Linux', MacOSX' and the one Git includes in compat/regex/: by using the (non-POSIX) REG_STARTEND flag, it is possible to tell the regexec() function that it should only look at the offsets between pmatch[0].rm_so and pmatch[0].rm_eo.
That is exactly what we need.
Since support for REG_STARTEND is so widespread by now, let's just introduce a helper function that uses it, and fall back to allocating and constructing a NUL-terminated when REG_STARTEND is not available.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> --- Makefile | 3 ++- git-compat-util.h | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile index df4f86b..c6f7f66 100644 --- a/Makefile +++ b/Makefile @@ -301,7 +301,8 @@ all:: # crashes due to allocation and free working on different 'heaps'. # It's defined automatically if USE_NED_ALLOCATOR is set. # -# Define NO_REGEX if you have no or inferior regex support in your C library. +# Define NO_REGEX if your C library lacks regex support with REG_STARTEND +# feature. # # Define HAVE_DEV_TTY if your system can open /dev/tty to interact with the # user. diff --git a/git-compat-util.h b/git-compat-util.h index 37cce07..8aab0c3 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -977,6 +977,19 @@ void git_qsort(void *base, size_t nmemb, size_t size, #define qsort git_qsort #endif +#ifndef REG_STARTEND +#error "Git requires REG_STARTEND support. Compile with NO_REGEX=NeedsStartEnd" +#endif + +static inline int regexec_buf(const regex_t *preg, const char *buf, size_t size, + size_t nmatch, regmatch_t pmatch[], int eflags) +{ + assert(nmatch > 0 && pmatch); + pmatch[0].rm_so = 0; + pmatch[0].rm_eo = size; + return regexec(preg, buf, nmatch, pmatch, eflags | REG_STARTEND); +} + #ifndef DIR_HAS_BSD_GROUP_SEMANTICS # define FORCE_DIR_SET_GID S_ISGID #else
-- 2.10.0.windows.1.10.g803177d