mirror of
https://github.com/postgres/postgres.git
synced 2026-03-27 04:44:15 -04:00
A corrupted string could cause code that iterates with pg_mblen() to overrun its buffer. Fix, by converting all callers to one of the following: 1. Callers with a null-terminated string now use pg_mblen_cstr(), which raises an "illegal byte sequence" error if it finds a terminator in the middle of the sequence. 2. Callers with a length or end pointer now use either pg_mblen_with_len() or pg_mblen_range(), for the same effect, depending on which of the two seems more convenient at each site. 3. A small number of cases pre-validate a string, and can use pg_mblen_unbounded(). The traditional pg_mblen() function and COPYCHAR macro still exist for backward compatibility, but are no longer used by core code and are hereby deprecated. The same applies to the t_isXXX() functions. Security: CVE-2026-2006 Backpatch-through: 14 Co-authored-by: Thomas Munro <thomas.munro@gmail.com> Co-authored-by: Noah Misch <noah@leadboat.com> Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi> Reported-by: Paul Gerste (as part of zeroday.cloud) Reported-by: Moritz Sanft (as part of zeroday.cloud)
71 lines
1.2 KiB
C
71 lines
1.2 KiB
C
/* contrib/ltree/crc32.c */
|
|
|
|
/*
|
|
* Implements CRC-32, as used in ltree.
|
|
*
|
|
* Note that the CRC is used in the on-disk format of GiST indexes, so we
|
|
* must stay backwards-compatible!
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
#include "ltree.h"
|
|
|
|
#include "crc32.h"
|
|
#include "utils/pg_crc.h"
|
|
#ifdef LOWER_NODE
|
|
#include "utils/pg_locale.h"
|
|
#endif
|
|
|
|
#ifdef LOWER_NODE
|
|
|
|
unsigned int
|
|
ltree_crc32_sz(const char *buf, int size)
|
|
{
|
|
pg_crc32 crc;
|
|
const char *p = buf;
|
|
const char *end = buf + size;
|
|
static pg_locale_t locale = NULL;
|
|
|
|
if (!locale)
|
|
locale = pg_database_locale();
|
|
|
|
INIT_TRADITIONAL_CRC32(crc);
|
|
while (size > 0)
|
|
{
|
|
char foldstr[UNICODE_CASEMAP_BUFSZ];
|
|
int srclen = pg_mblen_range(p, end);
|
|
size_t foldlen;
|
|
|
|
/* fold one codepoint at a time */
|
|
foldlen = pg_strfold(foldstr, UNICODE_CASEMAP_BUFSZ, p, srclen,
|
|
locale);
|
|
|
|
COMP_TRADITIONAL_CRC32(crc, foldstr, foldlen);
|
|
|
|
size -= srclen;
|
|
p += srclen;
|
|
}
|
|
FIN_TRADITIONAL_CRC32(crc);
|
|
return (unsigned int) crc;
|
|
}
|
|
|
|
#else
|
|
|
|
unsigned int
|
|
ltree_crc32_sz(const char *buf, int size)
|
|
{
|
|
pg_crc32 crc;
|
|
const char *p = buf;
|
|
|
|
INIT_TRADITIONAL_CRC32(crc);
|
|
while (size > 0)
|
|
{
|
|
COMP_TRADITIONAL_CRC32(crc, p, 1);
|
|
size--;
|
|
p++;
|
|
}
|
|
FIN_TRADITIONAL_CRC32(crc);
|
|
return (unsigned int) crc;
|
|
}
|
|
|
|
#endif /* !LOWER_NODE */
|