Re: [RFC PATCH v5 0/3] grep: almost no more leaks, hopefully no crashes
- From
Johannes Schindelin <johannes.schindelin@gmx.de>
- Date
- Aug 9, 2019, 21:26 UTC
- Message-ID
- <nycvar.QRO.7.76.6.1908092325480.46@tvgsbejvaqbjf.bet>
- In-Reply-To
- <d239326e-11c3-5875-13a8-f4123baea6eb@web.de>
Hi,
On Fri, 9 Aug 2019, René Scharfe wrote:
Show 10 quoted lines
> Am 09.08.19 um 13:24 schrieb Carlo Arenas: > > disregard this version, it still broken (and wouldn't even build on > > some cases), the reasons why are still unclear though but at least it > > might > > seem from the last known run in windows that segfaults were prevented > > at last and something was still off enough to trigger a BUG (shouldn't > > be a concern with V6 or later that do PCRE2 migration to NED fully, as > > agreed) > > So how about starting stupidly simple?
FWIW I am very much in favor of this approach.
Thanks, Dscho
Show 114 quoted lines
> You can test it everywhere, it just needs libpcre2. It works without
> that library as well (tested with "make USE_LIBPCRE= USE_LIBPCRE2=
> test"), but doesn't allocate anything in that case, of course. The
> character tables leak fix should be safe on top. If you detect
> performance issues then we can address them in additional patches.
>
> -- >8 --
> Subject: [PATCH] grep: use xmalloc() for all PCRE2 allocations
>
> Build a PCRE2 global custom context when compiling a pattern and use it
> to tell the library to use xmalloc() for allocations. This provides
> consistent out-of-memory handling and makes sure it uses a custom
> allocator, e.g. with USE_NED_ALLOCATOR.
>
> Signed-off-by: René Scharfe <l.s.r@web.de>
> ---
> The function names are ridiculously long, I tried to stay within 80
> characters per line but gave up in the end and just kept going without
> line breaks. Fits the "stupidly simple" approach..
>
> grep.c | 23 +++++++++++++++++------
> grep.h | 2 ++
> 2 files changed, 19 insertions(+), 6 deletions(-)
>
> diff --git a/grep.c b/grep.c
> index cd952ef5d3..44f4e38657 100644
> --- a/grep.c
> +++ b/grep.c
> @@ -482,6 +482,16 @@ static void free_pcre1_regexp(struct grep_pat *p)
> #endif /* !USE_LIBPCRE1 */
>
> #ifdef USE_LIBPCRE2
> +static void *pcre2_malloc(PCRE2_SIZE size, MAYBE_UNUSED void *memory_data)
> +{
> + return xmalloc(size);
> +}
> +
> +static void pcre2_free(void *pointer, MAYBE_UNUSED void *memory_data)
> +{
> + free(pointer);
> +}
> +
> static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt)
> {
> int error;
> @@ -495,12 +505,12 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
>
> assert(opt->pcre2);
>
> - p->pcre2_compile_context = NULL;
> + p->pcre2_general_context = pcre2_general_context_create(pcre2_malloc, pcre2_free, NULL);
> + p->pcre2_compile_context = pcre2_compile_context_create(p->pcre2_general_context);
>
> if (opt->ignore_case) {
> if (has_non_ascii(p->pattern)) {
> - character_tables = pcre2_maketables(NULL);
> - p->pcre2_compile_context = pcre2_compile_context_create(NULL);
> + character_tables = pcre2_maketables(p->pcre2_general_context);
> pcre2_set_character_tables(p->pcre2_compile_context, character_tables);
> }
> options |= PCRE2_CASELESS;
> @@ -513,7 +523,7 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
> p->pcre2_compile_context);
>
> if (p->pcre2_pattern) {
> - p->pcre2_match_data = pcre2_match_data_create_from_pattern(p->pcre2_pattern, NULL);
> + p->pcre2_match_data = pcre2_match_data_create_from_pattern(p->pcre2_pattern, p->pcre2_general_context);
> if (!p->pcre2_match_data)
> die("Couldn't allocate PCRE2 match data");
> } else {
> @@ -550,10 +560,10 @@ static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt
> return;
> }
>
> - p->pcre2_jit_stack = pcre2_jit_stack_create(1, 1024 * 1024, NULL);
> + p->pcre2_jit_stack = pcre2_jit_stack_create(1, 1024 * 1024, p->pcre2_general_context);
> if (!p->pcre2_jit_stack)
> die("Couldn't allocate PCRE2 JIT stack");
> - p->pcre2_match_context = pcre2_match_context_create(NULL);
> + p->pcre2_match_context = pcre2_match_context_create(p->pcre2_general_context);
> if (!p->pcre2_match_context)
> die("Couldn't allocate PCRE2 match context");
> pcre2_jit_stack_assign(p->pcre2_match_context, NULL, p->pcre2_jit_stack);
> @@ -605,6 +615,7 @@ static void free_pcre2_pattern(struct grep_pat *p)
> pcre2_match_data_free(p->pcre2_match_data);
> pcre2_jit_stack_free(p->pcre2_jit_stack);
> pcre2_match_context_free(p->pcre2_match_context);
> + pcre2_general_context_free(p->pcre2_general_context);
> }
> #else /* !USE_LIBPCRE2 */
> static void compile_pcre2_pattern(struct grep_pat *p, const struct grep_opt *opt)
> diff --git a/grep.h b/grep.h
> index 1875880f37..73b8b87a3a 100644
> --- a/grep.h
> +++ b/grep.h
> @@ -28,6 +28,7 @@ typedef int pcre_jit_stack;
> #else
> typedef int pcre2_code;
> typedef int pcre2_match_data;
> +typedef int pcre2_general_context;
> typedef int pcre2_compile_context;
> typedef int pcre2_match_context;
> typedef int pcre2_jit_stack;
> @@ -93,6 +94,7 @@ struct grep_pat {
> int pcre1_jit_on;
> pcre2_code *pcre2_pattern;
> pcre2_match_data *pcre2_match_data;
> + pcre2_general_context *pcre2_general_context;
> pcre2_compile_context *pcre2_compile_context;
> pcre2_match_context *pcre2_match_context;
> pcre2_jit_stack *pcre2_jit_stack;
> --
> 2.22.0
>