Merge branch 'js/regexec-buf' into maint
authorJunio C Hamano <gitster@pobox.com>
Tue, 28 Mar 2017 20:52:24 +0000 (13:52 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 28 Mar 2017 20:52:24 +0000 (13:52 -0700)
Fix for potential segv introduced in v2.11.0 and later (also
v2.10.2).

* js/regexec-buf:
pickaxe: fix segfault with '-S<...> --pickaxe-regex'

1  2 
diffcore-pickaxe.c
diff --combined diffcore-pickaxe.c
index 9795ca1c159a5177b1b7031a87c8f8bd5e5be3d5,e627140b85659117790f361f7ab49746bec7b950..341529b5a865ae6460f50d8593d52497059f2408
@@@ -7,8 -7,6 +7,8 @@@
  #include "diffcore.h"
  #include "xdiff-interface.h"
  #include "kwset.h"
 +#include "commit.h"
 +#include "quote.h"
  
  typedef int (*pickaxe_fn)(mmfile_t *one, mmfile_t *two,
                          struct diff_options *o,
@@@ -81,12 -79,15 +81,15 @@@ static unsigned int contains(mmfile_t *
                regmatch_t regmatch;
                int flags = 0;
  
-               while (*data &&
+               while (sz && *data &&
                       !regexec_buf(regexp, data, sz, 1, &regmatch, flags)) {
                        flags |= REG_NOTBOL;
                        data += regmatch.rm_eo;
-                       if (*data && regmatch.rm_so == regmatch.rm_eo)
+                       sz -= regmatch.rm_eo;
+                       if (sz && *data && regmatch.rm_so == regmatch.rm_eo) {
                                data++;
+                               sz--;
+                       }
                        cnt++;
                }
  
@@@ -198,18 -199,6 +201,18 @@@ static void pickaxe(struct diff_queue_s
        *q = outq;
  }
  
 +static void regcomp_or_die(regex_t *regex, const char *needle, int cflags)
 +{
 +      int err = regcomp(regex, needle, cflags);
 +      if (err) {
 +              /* The POSIX.2 people are surely sick */
 +              char errbuf[1024];
 +              regerror(err, regex, errbuf, 1024);
 +              regfree(regex);
 +              die("invalid regex: %s", errbuf);
 +      }
 +}
 +
  void diffcore_pickaxe(struct diff_options *o)
  {
        const char *needle = o->pickaxe;
        kwset_t kws = NULL;
  
        if (opts & (DIFF_PICKAXE_REGEX | DIFF_PICKAXE_KIND_G)) {
 -              int err;
                int cflags = REG_EXTENDED | REG_NEWLINE;
                if (DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE))
                        cflags |= REG_ICASE;
 -              err = regcomp(&regex, needle, cflags);
 -              if (err) {
 -                      /* The POSIX.2 people are surely sick */
 -                      char errbuf[1024];
 -                      regerror(err, &regex, errbuf, 1024);
 -                      regfree(&regex);
 -                      die("invalid regex: %s", errbuf);
 -              }
 +              regcomp_or_die(&regex, needle, cflags);
 +              regexp = &regex;
 +      } else if (DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE) &&
 +                 has_non_ascii(needle)) {
 +              struct strbuf sb = STRBUF_INIT;
 +              int cflags = REG_NEWLINE | REG_ICASE;
 +
 +              basic_regex_quote_buf(&sb, needle);
 +              regcomp_or_die(&regex, sb.buf, cflags);
 +              strbuf_release(&sb);
                regexp = &regex;
        } else {
                kws = kwsalloc(DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE)