diff options
author | Tom Lane | 2021-03-19 01:44:42 +0000 |
---|---|---|
committer | Tom Lane | 2021-03-19 02:22:47 +0000 |
commit | d303849b059c3c315e5a8d4239016f8328f3296c (patch) | |
tree | 17ab9fa9eeb00fe51c7fdcbf6415b316dd909f79 /src/include | |
parent | 415ffdc2205e209b6a73fb42a3fdd6e57e16c7b2 (diff) |
Don't leak compiled regex(es) when an ispell cache entry is dropped.
The text search cache mechanisms assume that we can clean up
an invalidated dictionary cache entry simply by resetting the
associated long-lived memory context. However, that does not work
for ispell affixes that make use of regular expressions, because
the regex library deals in plain old malloc. Hence, we leaked
compiled regex(es) any time we dropped such a cache entry. That
could quickly add up, since even a fairly trivial regex can use up
tens of kB, and a large one can eat megabytes. Add a memory context
callback to ensure that a regex gets freed when its owning cache
entry is cleared.
Found via valgrind testing.
This problem is ancient, so back-patch to all supported branches.
Discussion: https://postgr.es/m/3816764.1616104288@sss.pgh.pa.us
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/tsearch/dicts/spell.h | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/src/include/tsearch/dicts/spell.h b/src/include/tsearch/dicts/spell.h index 9847e30208..e03ed42372 100644 --- a/src/include/tsearch/dicts/spell.h +++ b/src/include/tsearch/dicts/spell.h @@ -82,6 +82,17 @@ typedef struct spell_struct #define SPELLHDRSZ (offsetof(SPELL, word)) /* + * If an affix uses a regex, we have to store that separately in a struct + * that won't move around when arrays of affixes are enlarged or sorted. + * This is so that it can be found to be cleaned up at context destruction. + */ +typedef struct aff_regex_struct +{ + regex_t regex; + MemoryContextCallback mcallback; +} aff_regex_struct; + +/* * Represents an entry in an affix list. */ typedef struct aff_struct @@ -97,7 +108,7 @@ typedef struct aff_struct char *repl; union { - regex_t regex; + aff_regex_struct *pregex; Regis regis; } reg; } AFFIX; |