From d1ce2c40a15443891ddf9c2340cca66d5e141c92 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Tue, 15 Oct 2024 08:01:41 +0200 Subject: [PATCH 3/3] WIP: Add pg_unset_regex_collation() Add a function pg_unset_regex_collation() that complements pg_set_regex_collation(). This unsets the global locale variable for regular expression use. This also adds assertions into both functions to make sure they are used correctly in pairs. This allows us to detect if pg_set_regex_collation() is not called when it should have been. Before, this would not be detected but the locale settings lingering from a previous use would be used. --- src/backend/regex/regc_pg_locale.c | 10 ++++++++++ src/backend/regex/regcomp.c | 9 ++++++++- src/backend/regex/regexec.c | 8 +++++--- src/include/regex/regguts.h | 1 + 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/backend/regex/regc_pg_locale.c b/src/backend/regex/regc_pg_locale.c index 4691e796385..8f38507b4bf 100644 --- a/src/backend/regex/regc_pg_locale.c +++ b/src/backend/regex/regc_pg_locale.c @@ -222,6 +222,8 @@ pg_set_regex_collation(Oid collation) { pg_locale_t locale = 0; + Assert(!pg_regex_locale); + if (!OidIsValid(collation)) { /* @@ -258,6 +260,14 @@ pg_set_regex_collation(Oid collation) pg_regex_locale = locale; } +void +pg_unset_regex_collation(void) +{ + Assert(pg_regex_locale); + pg_regex_locale = 0; +} + + static int pg_wc_isdigit(pg_wchar c) { diff --git a/src/backend/regex/regcomp.c b/src/backend/regex/regcomp.c index 8a6cfb2973d..f1442272065 100644 --- a/src/backend/regex/regcomp.c +++ b/src/backend/regex/regcomp.c @@ -385,7 +385,7 @@ pg_regcomp(regex_t *re, FILE *debug = (FILE *) NULL; #endif -#define CNOERR() { if (ISERR()) return freev(v, v->err); } +#define CNOERR() { if (ISERR()) { pg_unset_regex_collation(); return freev(v, v->err); } } /* sanity checks */ @@ -433,7 +433,10 @@ pg_regcomp(regex_t *re, /* more complex setup, malloced things */ re->re_guts = VS(MALLOC(sizeof(struct guts))); if (re->re_guts == NULL) + { + pg_unset_regex_collation(); return freev(v, REG_ESPACE); + } g = (struct guts *) re->re_guts; g->tree = NULL; initcm(v, &g->cmap); @@ -446,7 +449,10 @@ pg_regcomp(regex_t *re, /* set up a reasonably-sized transient cvec for getcvec usage */ v->cv = newcvec(100, 20); if (v->cv == NULL) + { + pg_unset_regex_collation(); return freev(v, REG_ESPACE); + } /* parsing */ lexstart(v); /* also handles prefixes */ @@ -542,6 +548,7 @@ pg_regcomp(regex_t *re, } #endif + pg_unset_regex_collation(); assert(v->err == 0); return freev(v, 0); } diff --git a/src/backend/regex/regexec.c b/src/backend/regex/regexec.c index 2a1d5bebda3..406fd2f7a1b 100644 --- a/src/backend/regex/regexec.c +++ b/src/backend/regex/regexec.c @@ -212,9 +212,6 @@ pg_regexec(regex_t *re, if (search_start > len) return REG_NOMATCH; - /* Initialize locale-dependent support */ - pg_set_regex_collation(re->re_collation); - /* setup */ v->re = re; v->g = (struct guts *) re->re_guts; @@ -257,6 +254,10 @@ pg_regexec(regex_t *re, v->ladfas = NULL; v->lblastcss = NULL; v->lblastcp = NULL; + + /* Initialize locale-dependent support */ + pg_set_regex_collation(re->re_collation); + /* below this point, "goto cleanup" will behave sanely */ assert(v->g->ntree >= 0); @@ -326,6 +327,7 @@ pg_regexec(regex_t *re, /* clean up */ cleanup: + pg_unset_regex_collation(); if (v->pmatch != pmatch && v->pmatch != mat) FREE(v->pmatch); if (v->subdfas != NULL) diff --git a/src/include/regex/regguts.h b/src/include/regex/regguts.h index 3ca3647e118..a35b85b463c 100644 --- a/src/include/regex/regguts.h +++ b/src/include/regex/regguts.h @@ -545,4 +545,5 @@ struct guts /* prototypes for functions that are exported from regcomp.c to regexec.c */ extern void pg_set_regex_collation(Oid collation); +extern void pg_unset_regex_collation(void); extern color pg_reg_getcolor(struct colormap *cm, chr c); -- 2.47.0