since-v3.diff.txt
text/plain
Filename: since-v3.diff.txt
Type: text/plain
Part: 0
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index 5318719acb..1394ecaa2b 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -1116,7 +1116,7 @@ prepare_cert_name(char *name)
#undef MAXLEN
- return pg_clean_ascii(truncated);
+ return pg_clean_ascii(truncated, 0);
}
/*
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 5e8cd770c0..52fb2e52f1 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -2284,7 +2284,7 @@ retry1:
*/
if (strcmp(nameptr, "application_name") == 0)
{
- port->application_name = pg_clean_ascii(valptr);
+ port->application_name = pg_clean_ascii(valptr, 0);
}
}
offset = valoffset + strlen(valptr) + 1;
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 60400752e5..2f99fe9a6d 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -12479,9 +12479,18 @@ assign_maintenance_io_concurrency(int newval, void *extra)
static bool
check_application_name(char **newval, void **extra, GucSource source)
{
+ char *clean;
+
/* Only allow clean ASCII chars in the application name */
- *newval = guc_strdup(ERROR, pg_clean_ascii(*newval));
+ clean = pg_clean_ascii(*newval, MCXT_ALLOC_NO_OOM);
+ if (!clean)
+ return false;
+
+ clean = guc_strdup(WARNING, clean);
+ if (!clean)
+ return false;
+ *newval = clean;
return true;
}
@@ -12495,9 +12504,18 @@ assign_application_name(const char *newval, void *extra)
static bool
check_cluster_name(char **newval, void **extra, GucSource source)
{
+ char *clean;
+
/* Only allow clean ASCII chars in the cluster name */
- *newval = guc_strdup(ERROR, pg_clean_ascii(*newval));
+ clean = pg_clean_ascii(*newval, MCXT_ALLOC_NO_OOM);
+ if (!clean)
+ return false;
+
+ clean = guc_strdup(WARNING, clean);
+ if (!clean)
+ return false;
+ *newval = clean;
return true;
}
diff --git a/src/common/string.c b/src/common/string.c
index db15324c62..97b3d45d36 100644
--- a/src/common/string.c
+++ b/src/common/string.c
@@ -62,7 +62,10 @@ strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
/*
* pg_clean_ascii -- Replace any non-ASCII chars with a "\xXX" string
*
- * Makes a palloc'd copy of the string passed in, which must be '\0'-terminated.
+ * Makes a newly allocated copy of the string passed in, which must be
+ * '\0'-terminated. In the backend, additional alloc_flags may be provided and
+ * will be passed as-is to palloc_extended(); in the frontend, alloc_flags is
+ * ignored and the copy is malloc'd.
*
* This function exists specifically to deal with filtering out
* non-ASCII characters in a few places where the client can provide an almost
@@ -80,23 +83,46 @@ strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
* for now.
*/
char *
-pg_clean_ascii(const char *str)
+pg_clean_ascii(const char *str, int alloc_flags)
{
- StringInfoData buf;
- const char *p;
+ size_t dstlen;
+ char *dst;
+ const char *p;
+ size_t i = 0;
- initStringInfo(&buf);
+ /* Worst case, each byte can become four bytes, plus a null terminator. */
+ dstlen = strlen(str) * 4 + 1;
+
+#ifdef FRONTEND
+ dst = malloc(dstlen);
+#else
+ dst = palloc_extended(dstlen, alloc_flags);
+#endif
+
+ if (!dst)
+ return NULL;
for (p = str; *p != '\0'; p++)
{
+
/* Only allow clean ASCII chars in the string */
if (*p < 32 || *p > 126)
- appendStringInfo(&buf, "\\x%02x", (unsigned char) *p);
+ {
+ Assert(i < (dstlen - 3));
+ snprintf(&dst[i], dstlen - i, "\\x%02x", (unsigned char) *p);
+ i += 4;
+ }
else
- appendStringInfoChar(&buf, *p);
+ {
+ Assert(i < dstlen);
+ dst[i] = *p;
+ i++;
+ }
}
- return buf.data;
+ Assert(i < dstlen);
+ dst[i] = '\0';
+ return dst;
}
diff --git a/src/include/common/string.h b/src/include/common/string.h
index d10d0c9cbf..3d59172151 100644
--- a/src/include/common/string.h
+++ b/src/include/common/string.h
@@ -24,7 +24,7 @@ typedef struct PromptInterruptContext
extern bool pg_str_endswith(const char *str, const char *end);
extern int strtoint(const char *pg_restrict str, char **pg_restrict endptr,
int base);
-extern char *pg_clean_ascii(const char *str);
+extern char *pg_clean_ascii(const char *str, int alloc_flags);
extern int pg_strip_crlf(char *str);
extern bool pg_is_ascii(const char *str);