#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,
 {
        struct diffgrep_cb *data = priv;
        regmatch_t regmatch;
-       int hold;
 
        if (line[0] != '+' && line[0] != '-')
                return;
                 * caller early.
                 */
                return;
-       /* Yuck -- line ought to be "const char *"! */
-       hold = line[len];
-       line[len] = '\0';
-       data->hit = !regexec(data->regexp, line + 1, 1, ®match, 0);
-       line[len] = hold;
+       data->hit = !regexec_buf(data->regexp, line + 1, len - 1, 1,
+                                ®match, 0);
 }
 
 static int diff_grep(mmfile_t *one, mmfile_t *two,
        xdemitconf_t xecfg;
 
        if (!one)
-               return !regexec(regexp, two->ptr, 1, ®match, 0);
+               return !regexec_buf(regexp, two->ptr, two->size,
+                                   1, ®match, 0);
        if (!two)
-               return !regexec(regexp, one->ptr, 1, ®match, 0);
+               return !regexec_buf(regexp, one->ptr, one->size,
+                                   1, ®match, 0);
 
        /*
         * We have both sides; need to run textual diff and see if
                regmatch_t regmatch;
                int flags = 0;
 
-               assert(data[sz] == '\0');
-               while (*data && !regexec(regexp, data, 1, ®match, flags)) {
+               while (sz && *data &&
+                      !regexec_buf(regexp, data, sz, 1, ®match, 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++;
                }
 
        *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(®ex, needle, cflags);
-               if (err) {
-                       /* The POSIX.2 people are surely sick */
-                       char errbuf[1024];
-                       regerror(err, ®ex, errbuf, 1024);
-                       regfree(®ex);
-                       die("invalid regex: %s", errbuf);
-               }
+               regcomp_or_die(®ex, needle, cflags);
+               regexp = ®ex;
+       } 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(®ex, sb.buf, cflags);
+               strbuf_release(&sb);
                regexp = ®ex;
        } else {
                kws = kwsalloc(DIFF_OPT_TST(o, PICKAXE_IGNORE_CASE)