Skip to content

Commit f2a3529

Browse files
committed
Merge branch 'cb/pcre2-chartables-leakfix' into jch
* 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
2 parents cf2c7f2 + 10da030 commit f2a3529

File tree

3 files changed

+47
-3
lines changed

3 files changed

+47
-3
lines changed

builtin/grep.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,5 +1147,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
11471147
run_pager(&opt, prefix);
11481148
clear_pathspec(&pathspec);
11491149
free_grep_patterns(&opt);
1150+
grep_destroy();
11501151
return !hit;
11511152
}

grep.c

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,20 @@ static int grep_source_is_binary(struct grep_source *gs,
1616

1717
static struct grep_opt grep_defaults;
1818

19+
#ifdef USE_LIBPCRE2
20+
static pcre2_general_context *pcre2_global_context;
21+
22+
static void *pcre2_malloc(PCRE2_SIZE size, MAYBE_UNUSED void *memory_data)
23+
{
24+
return malloc(size);
25+
}
26+
27+
static void pcre2_free(void *pointer, MAYBE_UNUSED void *memory_data)
28+
{
29+
return free(pointer);
30+
}
31+
#endif
32+
1933
static const char *color_grep_slots[] = {
2034
[GREP_COLOR_CONTEXT] = "context",
2135
[GREP_COLOR_FILENAME] = "filename",
@@ -150,12 +164,28 @@ int grep_config(const char *var, const char *value, void *cb)
150164
* Initialize one instance of grep_opt and copy the
151165
* default values from the template we read the configuration
152166
* information in an earlier call to git_config(grep_config).
167+
*
168+
* If using PCRE, make sure that the library is configured
169+
* to use the same allocator as Git (e.g. nedmalloc on Windows).
170+
*
171+
* Any allocated memory needs to be released in grep_destroy().
153172
*/
154173
void grep_init(struct grep_opt *opt, struct repository *repo, const char *prefix)
155174
{
156175
struct grep_opt *def = &grep_defaults;
157176
int i;
158177

178+
#if defined(USE_LIBPCRE2)
179+
if (!pcre2_global_context)
180+
pcre2_global_context = pcre2_general_context_create(
181+
pcre2_malloc, pcre2_free, NULL);
182+
#endif
183+
184+
#ifdef USE_LIBPCRE1
185+
pcre_malloc = malloc;
186+
pcre_free = free;
187+
#endif
188+
159189
memset(opt, 0, sizeof(*opt));
160190
opt->repo = repo;
161191
opt->prefix = prefix;
@@ -178,6 +208,13 @@ void grep_init(struct grep_opt *opt, struct repository *repo, const char *prefix
178208
color_set(opt->colors[i], def->colors[i]);
179209
}
180210

211+
void grep_destroy(void)
212+
{
213+
#ifdef USE_LIBPCRE2
214+
pcre2_general_context_free(pcre2_global_context);
215+
#endif
216+
}
217+
181218
static void grep_set_pattern_type_option(enum grep_pattern_type pattern_type, struct grep_opt *opt)
182219
{
183220
/*
@@ -461,7 +498,6 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
461498
PCRE2_UCHAR errbuf[256];
462499
PCRE2_SIZE erroffset;
463500
int options = PCRE2_MULTILINE;
464-
const uint8_t *character_tables = NULL;
465501
int jitret;
466502
int patinforet;
467503
size_t jitsizearg;
@@ -470,11 +506,15 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
470506

471507
p->pcre2_compile_context = NULL;
472508

509+
/* pcre2_global_context is initialized in append_grep_pattern */
473510
if (opt->ignore_case) {
474511
if (!opt->ignore_locale && has_non_ascii(p->pattern)) {
475-
character_tables = pcre2_maketables(NULL);
512+
if (!pcre2_global_context)
513+
BUG("pcre2_global_context uninitialized");
514+
p->pcre2_tables = pcre2_maketables(pcre2_global_context);
476515
p->pcre2_compile_context = pcre2_compile_context_create(NULL);
477-
pcre2_set_character_tables(p->pcre2_compile_context, character_tables);
516+
pcre2_set_character_tables(p->pcre2_compile_context,
517+
p->pcre2_tables);
478518
}
479519
options |= PCRE2_CASELESS;
480520
}
@@ -571,6 +611,7 @@ static void free_pcre2_pattern(struct grep_pat *p)
571611
pcre2_compile_context_free(p->pcre2_compile_context);
572612
pcre2_code_free(p->pcre2_pattern);
573613
pcre2_match_data_free(p->pcre2_match_data);
614+
free((void *)p->pcre2_tables);
574615
}
575616
#else /* !USE_LIBPCRE2 */
576617
static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt)

grep.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ struct grep_pat {
7878
pcre2_code *pcre2_pattern;
7979
pcre2_match_data *pcre2_match_data;
8080
pcre2_compile_context *pcre2_compile_context;
81+
const uint8_t *pcre2_tables;
8182
uint32_t pcre2_jit_on;
8283
unsigned fixed:1;
8384
unsigned is_fixed:1;
@@ -172,6 +173,7 @@ struct grep_opt {
172173
void init_grep_defaults(struct repository *);
173174
int grep_config(const char *var, const char *value, void *);
174175
void grep_init(struct grep_opt *, struct repository *repo, const char *prefix);
176+
void grep_destroy(void);
175177
void grep_commit_pattern_type(enum grep_pattern_type, struct grep_opt *opt);
176178

177179
void append_grep_pat(struct grep_opt *opt, const char *pat, size_t patlen, const char *origin, int no, enum grep_pat_token t);

0 commit comments

Comments
 (0)