]> git.ipfire.org Git - thirdparty/git.git/blobdiff - grep.c
Git 2.24
[thirdparty/git.git] / grep.c
diff --git a/grep.c b/grep.c
index 0bb4cbd3d82ceef5517905a35a7f6820b7fb555a..b7ae5a442a624810471cc4dc8ab84cd1a35c963a 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -16,6 +16,20 @@ static int grep_source_is_binary(struct grep_source *gs,
 
 static struct grep_opt grep_defaults;
 
+#ifdef USE_LIBPCRE2
+static pcre2_general_context *pcre2_global_context;
+
+static void *pcre2_malloc(PCRE2_SIZE size, MAYBE_UNUSED void *memory_data)
+{
+       return malloc(size);
+}
+
+static void pcre2_free(void *pointer, MAYBE_UNUSED void *memory_data)
+{
+       return free(pointer);
+}
+#endif
+
 static const char *color_grep_slots[] = {
        [GREP_COLOR_CONTEXT]        = "context",
        [GREP_COLOR_FILENAME]       = "filename",
@@ -150,12 +164,28 @@ int grep_config(const char *var, const char *value, void *cb)
  * Initialize one instance of grep_opt and copy the
  * default values from the template we read the configuration
  * information in an earlier call to git_config(grep_config).
+ *
+ * If using PCRE, make sure that the library is configured
+ * to use the same allocator as Git (e.g. nedmalloc on Windows).
+ *
+ * Any allocated memory needs to be released in grep_destroy().
  */
 void grep_init(struct grep_opt *opt, struct repository *repo, const char *prefix)
 {
        struct grep_opt *def = &grep_defaults;
        int i;
 
+#if defined(USE_LIBPCRE2)
+       if (!pcre2_global_context)
+               pcre2_global_context = pcre2_general_context_create(
+                                       pcre2_malloc, pcre2_free, NULL);
+#endif
+
+#ifdef USE_LIBPCRE1
+       pcre_malloc = malloc;
+       pcre_free = free;
+#endif
+
        memset(opt, 0, sizeof(*opt));
        opt->repo = repo;
        opt->prefix = prefix;
@@ -178,6 +208,13 @@ void grep_init(struct grep_opt *opt, struct repository *repo, const char *prefix
                color_set(opt->colors[i], def->colors[i]);
 }
 
+void grep_destroy(void)
+{
+#ifdef USE_LIBPCRE2
+       pcre2_general_context_free(pcre2_global_context);
+#endif
+}
+
 static void grep_set_pattern_type_option(enum grep_pattern_type pattern_type, struct grep_opt *opt)
 {
        /*
@@ -461,7 +498,6 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
        PCRE2_UCHAR errbuf[256];
        PCRE2_SIZE erroffset;
        int options = PCRE2_MULTILINE;
-       const uint8_t *character_tables = NULL;
        int jitret;
        int patinforet;
        size_t jitsizearg;
@@ -470,11 +506,15 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
 
        p->pcre2_compile_context = NULL;
 
+       /* pcre2_global_context is initialized in append_grep_pattern */
        if (opt->ignore_case) {
                if (!opt->ignore_locale && has_non_ascii(p->pattern)) {
-                       character_tables = pcre2_maketables(NULL);
+                       if (!pcre2_global_context)
+                               BUG("pcre2_global_context uninitialized");
+                       p->pcre2_tables = pcre2_maketables(pcre2_global_context);
                        p->pcre2_compile_context = pcre2_compile_context_create(NULL);
-                       pcre2_set_character_tables(p->pcre2_compile_context, character_tables);
+                       pcre2_set_character_tables(p->pcre2_compile_context,
+                                                       p->pcre2_tables);
                }
                options |= PCRE2_CASELESS;
        }
@@ -571,6 +611,7 @@ static void free_pcre2_pattern(struct grep_pat *p)
        pcre2_compile_context_free(p->pcre2_compile_context);
        pcre2_code_free(p->pcre2_pattern);
        pcre2_match_data_free(p->pcre2_match_data);
+       free((void *)p->pcre2_tables);
 }
 #else /* !USE_LIBPCRE2 */
 static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt)