]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Be more wary of false matches in initdb's replace_token().
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 5 Mar 2026 22:22:31 +0000 (17:22 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 5 Mar 2026 22:22:31 +0000 (17:22 -0500)
Do not replace the target string unless the occurrence is surrounded
by whitespace or line start/end.  This avoids potential false match
to a substring of a field.  While we've not had trouble with that
up to now, the next patch creates hazards of false matches to
POSTGRES within an ACL field.

There is one call site that needs adjustment, as it was presuming
it could write "::1" and have that match "::1/128".  For all the
others, this restriction is okay and strictly safer.

Author: Tom Lane <tgl@sss.pgh.pa.us>
Reviewed-by: Álvaro Herrera <alvherre@kurilemu.de>
Discussion: https://postgr.es/m/183292bb-4891-4c96-a3ca-e78b5e0e1358@dunslane.net

src/bin/initdb/initdb.c

index 6387c66289e2640a8e87e46a9d32c5c58f1453ab..f3174d79f32cb3e5fa364bdefe97ec1430b0f270 100644 (file)
@@ -461,7 +461,8 @@ add_stringlist_item(_stringlist **listhead, const char *str)
 
 /*
  * Modify the array of lines, replacing "token" by "replacement"
- * the first time it occurs on each line.
+ * the first time it occurs on each line.  To prevent false matches, the
+ * occurrence of "token" must be surrounded by whitespace or line start/end.
  *
  * The array must be a malloc'd array of individually malloc'd strings.
  * We free any discarded strings.
@@ -483,6 +484,7 @@ replace_token(char **lines, const char *token, const char *replacement)
        for (int i = 0; lines[i]; i++)
        {
                char       *where;
+               char       *endwhere;
                char       *newline;
                int                     pre;
 
@@ -490,6 +492,17 @@ replace_token(char **lines, const char *token, const char *replacement)
                if ((where = strstr(lines[i], token)) == NULL)
                        continue;
 
+               /*
+                * Reject false match.  Note a blind spot: we don't check for a valid
+                * match following a false match.  That case can't occur at present,
+                * so not worth complicating this code for it.
+                */
+               if (!(where == lines[i] || isspace((unsigned char) where[-1])))
+                       continue;
+               endwhere = where + strlen(token);
+               if (!(*endwhere == '\0' || isspace((unsigned char) *endwhere)))
+                       continue;
+
                /* if we get here a change is needed - set up new line */
 
                newline = (char *) pg_malloc(strlen(lines[i]) + diff + 1);
@@ -1501,11 +1514,11 @@ setup_config(void)
                        getaddrinfo("::1", NULL, &hints, &gai_result) != 0)
                {
                        conflines = replace_token(conflines,
-                                                                         "host    all             all             ::1",
-                                                                         "#host    all             all             ::1");
+                                                                         "host    all             all             ::1/128",
+                                                                         "#host    all             all             ::1/128");
                        conflines = replace_token(conflines,
-                                                                         "host    replication     all             ::1",
-                                                                         "#host    replication     all             ::1");
+                                                                         "host    replication     all             ::1/128",
+                                                                         "#host    replication     all             ::1/128");
                }
        }