Skip to content

Commit 00f1a1f

Browse files
committed
Back-patch pg_encoding_verifymbstr()/pg_encoding_verifymbchar() to v13.
A security fix will need those functions, so back-patch the v14+ functions to v13. When commit b80e106 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
1 parent bf085f6 commit 00f1a1f

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

src/common/wchar.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,6 +1597,72 @@ pg_encoding_verifymb(int encoding, const char *mbstr, int len)
15971597
pg_wchar_table[PG_SQL_ASCII].mbverify((const unsigned char *) mbstr, len));
15981598
}
15991599

1600+
/* v14+ function name, for easier backpatching */
1601+
int
1602+
pg_encoding_verifymbchar(int encoding, const char *mbstr, int len)
1603+
{
1604+
int ok_bytes = pg_encoding_verifymb(encoding, mbstr, len);
1605+
1606+
if (ok_bytes == 0)
1607+
return -1;
1608+
return ok_bytes;
1609+
}
1610+
1611+
/* replace v14+ function, adapted from pg_verify_mbstr_len */
1612+
int
1613+
pg_encoding_verifymbstr(int encoding, const char *mbstr, int len)
1614+
{
1615+
mbverifier mbverify;
1616+
int ok_bytes;
1617+
1618+
Assert(PG_VALID_ENCODING(encoding));
1619+
1620+
/*
1621+
* In single-byte encodings, we need only reject nulls (\0).
1622+
*/
1623+
if (pg_encoding_max_length(encoding) <= 1)
1624+
{
1625+
const char *nullpos = memchr(mbstr, 0, len);
1626+
1627+
if (nullpos == NULL)
1628+
return len;
1629+
return nullpos - mbstr;
1630+
}
1631+
1632+
/* fetch function pointer just once */
1633+
mbverify = pg_wchar_table[encoding].mbverify;
1634+
1635+
ok_bytes = 0;
1636+
1637+
while (len > 0)
1638+
{
1639+
int l;
1640+
1641+
/* fast path for ASCII-subset characters */
1642+
if (!IS_HIGHBIT_SET(*mbstr))
1643+
{
1644+
if (*mbstr != '\0')
1645+
{
1646+
ok_bytes++;
1647+
mbstr++;
1648+
len--;
1649+
continue;
1650+
}
1651+
return ok_bytes;
1652+
}
1653+
1654+
l = (*mbverify) ((const unsigned char *) mbstr, len);
1655+
1656+
if (l < 0)
1657+
return ok_bytes;
1658+
1659+
mbstr += l;
1660+
len -= l;
1661+
ok_bytes += l;
1662+
}
1663+
return ok_bytes;
1664+
}
1665+
16001666
/*
16011667
* fetch maximum length of a given encoding
16021668
*/

src/include/mb/pg_wchar.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,8 @@ extern int pg_encoding_mblen(int encoding, const char *mbstr);
556556
extern int pg_encoding_mblen_bounded(int encoding, const char *mbstr);
557557
extern int pg_encoding_dsplen(int encoding, const char *mbstr);
558558
extern int pg_encoding_verifymb(int encoding, const char *mbstr, int len);
559+
extern int pg_encoding_verifymbchar(int encoding, const char *mbstr, int len);
560+
extern int pg_encoding_verifymbstr(int encoding, const char *mbstr, int len);
559561
extern int pg_encoding_max_length(int encoding);
560562
extern int pg_valid_client_encoding(const char *name);
561563
extern int pg_valid_server_encoding(const char *name);

0 commit comments

Comments
 (0)