From ae65ca312f4dab71886b747fe810dc27548ca76d Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sat, 11 Aug 2007 19:16:41 +0000 Subject: [PATCH] Avoid memory leakage across successive calls of regexp_matches() or regexp_split_to_table() within a single query. This is only a partial solution, as it turns out that with enough matches per string these functions can also tickle a repalloc() misbehavior. But fixing that is a topic for a separate patch. --- src/backend/utils/adt/regexp.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/backend/utils/adt/regexp.c b/src/backend/utils/adt/regexp.c index 05c00deaf9..55901585a0 100644 --- a/src/backend/utils/adt/regexp.c +++ b/src/backend/utils/adt/regexp.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/regexp.c,v 1.72 2007/08/11 03:56:24 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/regexp.c,v 1.73 2007/08/11 19:16:41 tgl Exp $ * * Alistair Crooks added the code for the regex caching * agc - cached the regular expressions used - there's a good chance @@ -112,6 +112,7 @@ static regexp_matches_ctx *setup_regexp_matches(text *orig_str, text *pattern, bool force_glob, bool use_subpatterns, bool ignore_degenerate); +static void cleanup_regexp_matches(regexp_matches_ctx *matchctx); static ArrayType *build_regexp_matches_result(regexp_matches_ctx *matchctx); static Datum build_regexp_split_result(regexp_matches_ctx *splitctx); @@ -815,6 +816,9 @@ regexp_matches(PG_FUNCTION_ARGS) SRF_RETURN_NEXT(funcctx, PointerGetDatum(result_ary)); } + /* release space in multi-call ctx to avoid intraquery memory leak */ + cleanup_regexp_matches(matchctx); + SRF_RETURN_DONE(funcctx); } @@ -969,6 +973,21 @@ setup_regexp_matches(text *orig_str, text *pattern, text *flags, } /* + * cleanup_regexp_matches - release memory of a regexp_matches_ctx + */ +static void +cleanup_regexp_matches(regexp_matches_ctx *matchctx) +{ + pfree(matchctx->orig_str); + pfree(matchctx->match_locs); + if (matchctx->elems) + pfree(matchctx->elems); + if (matchctx->nulls) + pfree(matchctx->nulls); + pfree(matchctx); +} + +/* * build_regexp_matches_result - build output array for current match */ static ArrayType * @@ -1050,6 +1069,9 @@ regexp_split_to_table(PG_FUNCTION_ARGS) SRF_RETURN_NEXT(funcctx, result); } + /* release space in multi-call ctx to avoid intraquery memory leak */ + cleanup_regexp_matches(splitctx); + SRF_RETURN_DONE(funcctx); } @@ -1084,6 +1106,12 @@ Datum regexp_split_to_array(PG_FUNCTION_ARGS) splitctx->next_match++; } + /* + * We don't call cleanup_regexp_matches here; it would try to pfree + * the input string, which we didn't copy. The space is not in a + * long-lived memory context anyway. + */ + PG_RETURN_ARRAYTYPE_P(makeArrayResult(astate, CurrentMemoryContext)); } -- 2.11.0