]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Back-patch pg_encoding_verifymbstr()/pg_encoding_verifymbchar() to v13.
authorAndres Freund <andres@anarazel.de>
Mon, 10 Feb 2025 15:03:40 +0000 (10:03 -0500)
committerAndres Freund <andres@anarazel.de>
Mon, 10 Feb 2025 15:03:40 +0000 (10:03 -0500)
A security fix will need those functions, so back-patch the v14+ functions to
v13.

When commit b80e10638e36b9d2f0b39170c613837af2ca2aac introduced the v14+
implementation of pg_encoding_verifymbstr(), it added a callback to each
pg_wchar_table entry.  For simplicity and ABI stability, this instead
implements the function in terms of the existing per-character callback.

Author: Noah Misch <noah@leadboat.com>
Author: Andres Freund <andres@anarazel.de>
Security: CVE-2025-1094

src/common/wchar.c
src/include/mb/pg_wchar.h

index 0873480223628e8a979c89e441ea62bc3306a946..2d044ee4ffb0e9b9743daa2bf5459d497aaa3a00 100644 (file)
@@ -1597,6 +1597,72 @@ pg_encoding_verifymb(int encoding, const char *mbstr, int len)
                        pg_wchar_table[PG_SQL_ASCII].mbverify((const unsigned char *) mbstr, len));
 }
 
+/* v14+ function name, for easier backpatching */
+int
+pg_encoding_verifymbchar(int encoding, const char *mbstr, int len)
+{
+       int ok_bytes = pg_encoding_verifymb(encoding, mbstr, len);
+
+       if (ok_bytes == 0)
+               return -1;
+       return ok_bytes;
+}
+
+/* replace v14+ function, adapted from pg_verify_mbstr_len */
+int
+pg_encoding_verifymbstr(int encoding, const char *mbstr, int len)
+{
+       mbverifier      mbverify;
+       int                     ok_bytes;
+
+       Assert(PG_VALID_ENCODING(encoding));
+
+       /*
+        * In single-byte encodings, we need only reject nulls (\0).
+        */
+       if (pg_encoding_max_length(encoding) <= 1)
+       {
+               const char *nullpos = memchr(mbstr, 0, len);
+
+               if (nullpos == NULL)
+                       return len;
+               return nullpos - mbstr;
+       }
+
+       /* fetch function pointer just once */
+       mbverify = pg_wchar_table[encoding].mbverify;
+
+       ok_bytes = 0;
+
+       while (len > 0)
+       {
+               int                     l;
+
+               /* fast path for ASCII-subset characters */
+               if (!IS_HIGHBIT_SET(*mbstr))
+               {
+                       if (*mbstr != '\0')
+                       {
+                               ok_bytes++;
+                               mbstr++;
+                               len--;
+                               continue;
+                       }
+                       return ok_bytes;
+               }
+
+               l = (*mbverify) ((const unsigned char *) mbstr, len);
+
+               if (l < 0)
+                       return ok_bytes;
+
+               mbstr += l;
+               len -= l;
+               ok_bytes += l;
+       }
+       return ok_bytes;
+}
+
 /*
  * fetch maximum length of a given encoding
  */
index b43454b64cea76a76c16cb344fef9845c0912eb1..b0dbde45b33b556a2f608937f41f3c266367d316 100644 (file)
@@ -556,6 +556,8 @@ extern int  pg_encoding_mblen(int encoding, const char *mbstr);
 extern int     pg_encoding_mblen_bounded(int encoding, const char *mbstr);
 extern int     pg_encoding_dsplen(int encoding, const char *mbstr);
 extern int     pg_encoding_verifymb(int encoding, const char *mbstr, int len);
+extern int     pg_encoding_verifymbchar(int encoding, const char *mbstr, int len);
+extern int     pg_encoding_verifymbstr(int encoding, const char *mbstr, int len);
 extern int     pg_encoding_max_length(int encoding);
 extern int     pg_valid_client_encoding(const char *name);
 extern int     pg_valid_server_encoding(const char *name);