Commit e0ff2d4c authored by Junio C Hamano's avatar Junio C Hamano

Merge branch 'cb/pcre2-chartables-leakfix'

Leakfix.

* cb/pcre2-chartables-leakfix:
  grep: avoid leak of chartables in PCRE2
  grep: make PCRE2 aware of custom allocator
  grep: make PCRE1 aware of custom allocator
parents d45d7719 10da030a
...@@ -1147,5 +1147,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix) ...@@ -1147,5 +1147,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
run_pager(&opt, prefix); run_pager(&opt, prefix);
clear_pathspec(&pathspec); clear_pathspec(&pathspec);
free_grep_patterns(&opt); free_grep_patterns(&opt);
grep_destroy();
return !hit; return !hit;
} }
...@@ -16,6 +16,20 @@ static int grep_source_is_binary(struct grep_source *gs, ...@@ -16,6 +16,20 @@ static int grep_source_is_binary(struct grep_source *gs,
static struct grep_opt grep_defaults; 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[] = { static const char *color_grep_slots[] = {
[GREP_COLOR_CONTEXT] = "context", [GREP_COLOR_CONTEXT] = "context",
[GREP_COLOR_FILENAME] = "filename", [GREP_COLOR_FILENAME] = "filename",
...@@ -150,12 +164,28 @@ int grep_config(const char *var, const char *value, void *cb) ...@@ -150,12 +164,28 @@ int grep_config(const char *var, const char *value, void *cb)
* Initialize one instance of grep_opt and copy the * Initialize one instance of grep_opt and copy the
* default values from the template we read the configuration * default values from the template we read the configuration
* information in an earlier call to git_config(grep_config). * 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) void grep_init(struct grep_opt *opt, struct repository *repo, const char *prefix)
{ {
struct grep_opt *def = &grep_defaults; struct grep_opt *def = &grep_defaults;
int i; 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)); memset(opt, 0, sizeof(*opt));
opt->repo = repo; opt->repo = repo;
opt->prefix = prefix; opt->prefix = prefix;
...@@ -178,6 +208,13 @@ void grep_init(struct grep_opt *opt, struct repository *repo, const char *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]); 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) 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 ...@@ -461,7 +498,6 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
PCRE2_UCHAR errbuf[256]; PCRE2_UCHAR errbuf[256];
PCRE2_SIZE erroffset; PCRE2_SIZE erroffset;
int options = PCRE2_MULTILINE; int options = PCRE2_MULTILINE;
const uint8_t *character_tables = NULL;
int jitret; int jitret;
int patinforet; int patinforet;
size_t jitsizearg; size_t jitsizearg;
...@@ -470,11 +506,15 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt ...@@ -470,11 +506,15 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
p->pcre2_compile_context = NULL; p->pcre2_compile_context = NULL;
/* pcre2_global_context is initialized in append_grep_pattern */
if (opt->ignore_case) { if (opt->ignore_case) {
if (!opt->ignore_locale && has_non_ascii(p->pattern)) { 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); 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; options |= PCRE2_CASELESS;
} }
...@@ -571,6 +611,7 @@ static void free_pcre2_pattern(struct grep_pat *p) ...@@ -571,6 +611,7 @@ static void free_pcre2_pattern(struct grep_pat *p)
pcre2_compile_context_free(p->pcre2_compile_context); pcre2_compile_context_free(p->pcre2_compile_context);
pcre2_code_free(p->pcre2_pattern); pcre2_code_free(p->pcre2_pattern);
pcre2_match_data_free(p->pcre2_match_data); pcre2_match_data_free(p->pcre2_match_data);
free((void *)p->pcre2_tables);
} }
#else /* !USE_LIBPCRE2 */ #else /* !USE_LIBPCRE2 */
static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt) static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt)
......
...@@ -78,6 +78,7 @@ struct grep_pat { ...@@ -78,6 +78,7 @@ struct grep_pat {
pcre2_code *pcre2_pattern; pcre2_code *pcre2_pattern;
pcre2_match_data *pcre2_match_data; pcre2_match_data *pcre2_match_data;
pcre2_compile_context *pcre2_compile_context; pcre2_compile_context *pcre2_compile_context;
const uint8_t *pcre2_tables;
uint32_t pcre2_jit_on; uint32_t pcre2_jit_on;
unsigned fixed:1; unsigned fixed:1;
unsigned is_fixed:1; unsigned is_fixed:1;
...@@ -172,6 +173,7 @@ struct grep_opt { ...@@ -172,6 +173,7 @@ struct grep_opt {
void init_grep_defaults(struct repository *); void init_grep_defaults(struct repository *);
int grep_config(const char *var, const char *value, void *); int grep_config(const char *var, const char *value, void *);
void grep_init(struct grep_opt *, struct repository *repo, const char *prefix); void grep_init(struct grep_opt *, struct repository *repo, const char *prefix);
void grep_destroy(void);
void grep_commit_pattern_type(enum grep_pattern_type, struct grep_opt *opt); void grep_commit_pattern_type(enum grep_pattern_type, struct grep_opt *opt);
void append_grep_pat(struct grep_opt *opt, const char *pat, size_t patlen, const char *origin, int no, enum grep_pat_token t); void append_grep_pat(struct grep_opt *opt, const char *pat, size_t patlen, const char *origin, int no, enum grep_pat_token t);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment