Be more careful with error paths in pg_set_regex_collation().
authorJeff Davis
Thu, 5 Sep 2024 19:10:08 +0000 (12:10 -0700)
committerJeff Davis
Thu, 5 Sep 2024 19:10:08 +0000 (12:10 -0700)
Set global variables after error paths so that they don't end up in an
inconsistent state.

The inconsistent state doesn't lead to an actual problem, because
after an error, pg_set_regex_collation() will be called again before
the globals are accessed.

Change extracted from patch by Andreas Karlsson, though not discussed
explicitly.

Discussion: https://postgr.es/m/60929555-4709-40a7-b136-bcb44cff5a3c@proxel.se

src/backend/regex/regc_pg_locale.c

index 554a71e75a56d047f1a988923da058a6556621d1..35361c46a60ed8103a88870c89ed13e300e5aa2d 100644 (file)
@@ -231,6 +231,9 @@ static const unsigned char pg_char_properties[128] = {
 void
 pg_set_regex_collation(Oid collation)
 {
+   pg_locale_t locale = 0;
+   PG_Locale_Strategy strategy;
+
    if (!OidIsValid(collation))
    {
        /*
@@ -246,40 +249,41 @@ pg_set_regex_collation(Oid collation)
    if (lc_ctype_is_c(collation))
    {
        /* C/POSIX collations use this path regardless of database encoding */
-       pg_regex_strategy = PG_REGEX_STRATEGY_C;
-       pg_regex_locale = 0;
-       pg_regex_collation = C_COLLATION_OID;
+       strategy = PG_REGEX_STRATEGY_C;
+       collation = C_COLLATION_OID;
    }
    else
    {
-       pg_regex_locale = pg_newlocale_from_collation(collation);
+       locale = pg_newlocale_from_collation(collation);
 
-       if (!pg_locale_deterministic(pg_regex_locale))
+       if (!pg_locale_deterministic(locale))
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                     errmsg("nondeterministic collations are not supported for regular expressions")));
 
-       if (pg_regex_locale->provider == COLLPROVIDER_BUILTIN)
+       if (locale->provider == COLLPROVIDER_BUILTIN)
        {
            Assert(GetDatabaseEncoding() == PG_UTF8);
-           pg_regex_strategy = PG_REGEX_STRATEGY_BUILTIN;
+           strategy = PG_REGEX_STRATEGY_BUILTIN;
        }
 #ifdef USE_ICU
-       else if (pg_regex_locale->provider == COLLPROVIDER_ICU)
+       else if (locale->provider == COLLPROVIDER_ICU)
        {
-           pg_regex_strategy = PG_REGEX_STRATEGY_ICU;
+           strategy = PG_REGEX_STRATEGY_ICU;
        }
 #endif
        else
        {
            if (GetDatabaseEncoding() == PG_UTF8)
-               pg_regex_strategy = PG_REGEX_STRATEGY_LIBC_WIDE;
+               strategy = PG_REGEX_STRATEGY_LIBC_WIDE;
            else
-               pg_regex_strategy = PG_REGEX_STRATEGY_LIBC_1BYTE;
+               strategy = PG_REGEX_STRATEGY_LIBC_1BYTE;
        }
-
-       pg_regex_collation = collation;
    }
+
+   pg_regex_strategy = strategy;
+   pg_regex_locale = locale;
+   pg_regex_collation = collation;
 }
 
 static int