regex: use regexec_buf()

The new regexec_buf() function operates on buffers with an explicitly
specified length, rather than NUL-terminated strings.

We need to use this function whenever the buffer we want to pass to
regexec(3) may have been mmap(2)ed (and is hence not NUL-terminated).

Note: the original motivation for this patch was to fix a bug where
`git diff -G <regex>` would crash. This patch converts more callers,
though, some of which allocated to construct NUL-terminated strings,
or worse, modified buffers to temporarily insert NULs while calling
regexec(3).  By converting them to use regexec_buf(), the code has
become much cleaner.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Johannes Schindelin
2016-09-21 20:24:14 +02:00
committed by Junio C Hamano
parent 2f8952250a
commit b7d36ffca0
5 changed files with 17 additions and 33 deletions

View File

@ -21,7 +21,6 @@ static void diffgrep_consume(void *priv, char *line, unsigned long len)
{
struct diffgrep_cb *data = priv;
regmatch_t regmatch;
int hold;
if (line[0] != '+' && line[0] != '-')
return;
@ -31,11 +30,8 @@ static void diffgrep_consume(void *priv, char *line, unsigned long len)
* caller early.
*/
return;
/* Yuck -- line ought to be "const char *"! */
hold = line[len];
line[len] = '\0';
data->hit = !regexec(data->regexp, line + 1, 1, &regmatch, 0);
line[len] = hold;
data->hit = !regexec_buf(data->regexp, line + 1, len - 1, 1,
&regmatch, 0);
}
static int diff_grep(mmfile_t *one, mmfile_t *two,
@ -48,9 +44,11 @@ static int diff_grep(mmfile_t *one, mmfile_t *two,
xdemitconf_t xecfg;
if (!one)
return !regexec(regexp, two->ptr, 1, &regmatch, 0);
return !regexec_buf(regexp, two->ptr, two->size,
1, &regmatch, 0);
if (!two)
return !regexec(regexp, one->ptr, 1, &regmatch, 0);
return !regexec_buf(regexp, one->ptr, one->size,
1, &regmatch, 0);
/*
* We have both sides; need to run textual diff and see if
@ -81,8 +79,8 @@ static unsigned int contains(mmfile_t *mf, regex_t *regexp, kwset_t kws)
regmatch_t regmatch;
int flags = 0;
assert(data[sz] == '\0');
while (*data && !regexec(regexp, data, 1, &regmatch, flags)) {
while (*data &&
!regexec_buf(regexp, data, sz, 1, &regmatch, flags)) {
flags |= REG_NOTBOL;
data += regmatch.rm_eo;
if (*data && regmatch.rm_so == regmatch.rm_eo)