Fix some cases of indirectly casting away const.
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 5 Dec 2025 16:17:14 +0000 (11:17 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 5 Dec 2025 16:17:23 +0000 (11:17 -0500)
Newest versions of gcc are able to detect cases where code implicitly
casts away const by assigning the result of strchr() or a similar
function applied to a "const char *" value to a target variable
that's just "char *".  This of course creates a hazard of not getting
a compiler warning about scribbling on a string one was not supposed
to, so fixing up such cases is good.

This patch fixes a dozen or so places where we were doing that.
Most are trivial additions of "const" to the target variable,
since no actually-hazardous change was occurring.  There is one
place in ecpg.trailer where we were indeed violating the intention
of not modifying a string passed in as "const char *".  I believe
that's harmless not a live bug, but let's fix it by copying the
string before modifying it.

There is a remaining trouble spot in ecpg/preproc/variable.c,
which requires more complex surgery.  I've left that out of this
commit because I want to study that code a bit more first.

We probably will want to back-patch this once compilers that detect
this pattern get into wider circulation, but for now I'm just
going to apply it to master to see what the buildfarm says.

Thanks to Bertrand Drouvot for finding a couple more spots than
I had.

Author: Tom Lane <tgl@sss.pgh.pa.us>
Reviewed-by: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Discussion: https://postgr.es/m/1324889.1764886170@sss.pgh.pa.us

15 files changed:
src/backend/catalog/pg_type.c
src/backend/tsearch/spell.c
src/backend/utils/adt/formatting.c
src/backend/utils/adt/pg_locale.c
src/backend/utils/adt/xid8funcs.c
src/bin/pg_waldump/pg_waldump.c
src/bin/pgbench/pgbench.c
src/common/compression.c
src/interfaces/ecpg/pgtypeslib/datetime.c
src/interfaces/ecpg/preproc/ecpg.trailer
src/port/chklocale.c
src/port/getopt_long.c
src/port/win32setlocale.c
src/test/regress/pg_regress.c
src/timezone/zic.c

index 257c7da856832c0adcc73f7e4fd5fd4e0dc74faf..4a69a81b9fbafb93f1c2297b884c557f70299f03 100644 (file)
@@ -948,7 +948,7 @@ char *
 makeMultirangeTypeName(const char *rangeTypeName, Oid typeNamespace)
 {
    char       *buf;
-   char       *rangestr;
+   const char *rangestr;
 
    /*
     * If the range type name contains "range" then change that to
index 146801885d738ce6d932421145487c711435a5bf..0dab31f0ddb0d33e70520b640e5bf1924f16c4e8 100644 (file)
@@ -2320,7 +2320,7 @@ CheckCompoundAffixes(CMPDAffix **ptr, const char *word, int len, bool CheckInPla
    }
    else
    {
-       char       *affbegin;
+       const char *affbegin;
 
        while ((*ptr)->affix)
        {
index 5bfeda2ffde80999cc212ffe9d30916e99101742..c3cb022a40010a0f23cbbd0065c55e2e5dc8f526 100644 (file)
@@ -1046,8 +1046,9 @@ typedef struct NUMProc
    char       *number,         /* string with number   */
               *number_p,       /* pointer to current number position */
               *inout,          /* in / out buffer  */
-              *inout_p,        /* pointer to current inout position */
-              *last_relevant,  /* last relevant number after decimal point */
+              *inout_p;        /* pointer to current inout position */
+
+   const char *last_relevant,  /* last relevant number after decimal point */
 
               *L_negative_sign,    /* Locale */
               *L_positive_sign,
@@ -1118,7 +1119,7 @@ static FormatNode *NUM_cache(int len, NUMDesc *Num, const text *pars_str, bool *
 static char *int_to_roman(int number);
 static int roman_to_int(NUMProc *Np, size_t input_len);
 static void NUM_prepare_locale(NUMProc *Np);
-static char *get_last_relevant_decnum(const char *num);
+static const char *get_last_relevant_decnum(const char *num);
 static void NUM_numpart_from_char(NUMProc *Np, int id, size_t input_len);
 static void NUM_numpart_to_char(NUMProc *Np, int id);
 static char *NUM_processor(FormatNode *node, NUMDesc *Num, char *inout,
@@ -5297,10 +5298,10 @@ NUM_prepare_locale(NUMProc *Np)
  * If there is no decimal point, return NULL (which will result in same
  * behavior as if FM hadn't been specified).
  */
-static char *
+static const char *
 get_last_relevant_decnum(const char *num)
 {
-   char       *result,
+   const char *result,
               *p = strchr(num, '.');
 
 #ifdef DEBUG_TO_FROM_CHAR
index b26257c0a8df4e3a680a0090e8b46462095229a3..d73bab97c1577585d6dd3bf105956eceac45e278 100644 (file)
@@ -953,7 +953,7 @@ get_iso_localename(const char *winlocname)
    wchar_t     wc_locale_name[LOCALE_NAME_MAX_LENGTH];
    wchar_t     buffer[LOCALE_NAME_MAX_LENGTH];
    static char iso_lc_messages[LOCALE_NAME_MAX_LENGTH];
-   char       *period;
+   const char *period;
    int         len;
    int         ret_val;
 
index a211a10776749f2b27aeef42fb06acf8f63e20c1..4b3f7a69b3bcf2634299a7fa676be0188d9dac00 100644 (file)
@@ -194,7 +194,7 @@ is_visible_fxid(FullTransactionId value, const pg_snapshot *snap)
 #ifdef USE_BSEARCH_IF_NXIP_GREATER
    else if (snap->nxip > USE_BSEARCH_IF_NXIP_GREATER)
    {
-       void       *res;
+       const void *res;
 
        res = bsearch(&value, snap->xip, snap->nxip, sizeof(FullTransactionId),
                      cmp_fxid);
index c6d6ba79e446d0f8c0163bd126b13c3cc975c9f9..1c1ccf59f6537f5315b3237797658fb2b9fc1428 100644 (file)
@@ -160,7 +160,7 @@ create_fullpage_directory(char *path)
 static void
 split_path(const char *path, char **dir, char **fname)
 {
-   char       *sep;
+   const char *sep;
 
    /* split filepath into directory & filename */
    sep = strrchr(path, '/');
index 68774a59efdb22e39dbb59fd6e6c31421839e0e9..00593fab5e1d2c18ed0c193050ae965ebb31c761 100644 (file)
@@ -6254,7 +6254,7 @@ findBuiltin(const char *name)
 static int
 parseScriptWeight(const char *option, char **script)
 {
-   char       *sep;
+   const char *sep;
    int         weight;
 
    if ((sep = strrchr(option, WSEP)))
index 4c3c9fd7b507b5e9221e8410342ca4736ecc69e0..eb434542fbdf6e6dcbca0e9d800f9dafb386f5c0 100644 (file)
@@ -425,7 +425,7 @@ validate_compress_specification(pg_compress_specification *spec)
 void
 parse_compress_options(const char *option, char **algorithm, char **detail)
 {
-   char       *sep;
+   const char *sep;
    char       *endp;
    long        result;
 
index 1b253747fc403d7134cf9d2117c482c3c6590429..f43343b459499b53baa3fd6ea297e529fb37d4f7 100644 (file)
@@ -335,8 +335,8 @@ PGTYPESdate_defmt_asc(date * d, const char *fmt, const char *str)
     */
    int         token[3][2];
    int         token_values[3] = {-1, -1, -1};
-   char       *fmt_token_order;
-   char       *fmt_ystart,
+   const char *fmt_token_order;
+   const char *fmt_ystart,
               *fmt_mstart,
               *fmt_dstart;
    unsigned int i;
index 6f94b832a037f7b8b9377f3eb8ea960670967e26..e4c13fdd2b607f941fb345c5e03e89f50ab76ff5 100644 (file)
@@ -1975,12 +1975,14 @@ civarind: cvariable indicator
 
 char_civar: char_variable
    {
-       char       *ptr = strstr(@1, ".arr");
+       char       *var = loc_strdup(@1);
+       char       *ptr = strstr(var, ".arr");
 
        if (ptr)                /* varchar, we need the struct name here, not
                                 * the struct element */
            *ptr = '\0';
-       add_variable_to_head(&argsinsert, find_variable(@1), &no_indicator);
+       add_variable_to_head(&argsinsert, find_variable(var), &no_indicator);
+       @$ = var;
    }
    ;
 
index 034939f7fd2c02ddf02aeda1cc60f585d7c26366..023a7435c9bdaf5ddd58b650cdacb4604bdbb2f2 100644 (file)
@@ -202,7 +202,7 @@ static char *
 win32_get_codeset(const char *ctype)
 {
    char       *r = NULL;
-   char       *codepage;
+   const char *codepage;
    uint32      cp;
    WCHAR       wctype[LOCALE_NAME_MAX_LENGTH];
 
index f83de0dff97894647fff582753d71cb12ab1157d..20953db9db1e649e31bfd51810d9fdec18033d24 100644 (file)
@@ -62,7 +62,7 @@ getopt_long(int argc, char *const argv[],
            const struct option *longopts, int *longindex)
 {
    static char *place = EMSG;  /* option letter processing */
-   char       *oli;            /* option letter list index */
+   const char *oli;            /* option letter list index */
    static int  nonopt_start = -1;
    static bool force_nonopt = false;
 
index 7c0982439dbcddfc0b34f4fa38de13d3dbff0ed4..6e08494613249b3e296d0b260f5431535c3a7ffc 100644 (file)
@@ -119,9 +119,9 @@ map_locale(const struct locale_map *map, const char *locale)
        const char *needle_start = map[i].locale_name_start;
        const char *needle_end = map[i].locale_name_end;
        const char *replacement = map[i].replacement;
-       char       *match;
-       char       *match_start = NULL;
-       char       *match_end = NULL;
+       const char *match;
+       const char *match_start = NULL;
+       const char *match_end = NULL;
 
        match = strstr(locale, needle_start);
        if (match)
@@ -148,7 +148,7 @@ map_locale(const struct locale_map *map, const char *locale)
            /* Found a match. Replace the matched string. */
            int         matchpos = match_start - locale;
            int         replacementlen = strlen(replacement);
-           char       *rest = match_end;
+           const char *rest = match_end;
            int         restlen = strlen(rest);
 
            /* check that the result fits in the static buffer */
index efc41fca2ba791535ec41f436b670ac353499456..58d41207605dc29ab3f2c97cbdfdad1e165fcb6d 100644 (file)
@@ -693,7 +693,7 @@ static
 const char *
 get_expectfile(const char *testname, const char *file)
 {
-   char       *file_type;
+   const char *file_type;
    _resultmap *rm;
 
    /*
index a8c1de9910db15ed5f904a3e9ef8dec4366800d1..8dcc7b337a770323d1223e7e9dde865ecad5ad84 100644 (file)
@@ -2620,7 +2620,7 @@ doabbr(char *abbr, struct zone const *zp, char const *letters,
       bool isdst, zic_t save, bool doquotes)
 {
    char       *cp;
-   char       *slashp;
+   char const *slashp;
    size_t      len;
    char const *format = zp->z_format;