1
0
mirror of https://github.com/postgres/postgres.git synced 2025-10-25 13:17:41 +03:00

Fix convert_case(), introduced in 5c40364dd6.

Check source length before checking for NUL terminator to avoid
reading one byte past the string end. Also fix unreachable bug when
caller does not expect NUL-terminated result.

Add unit test coverage of convert_case() in case_test.c, which makes
it easier to reproduce the valgrind failure.

Discussion: https://postgr.es/m/7a9fd36d-7a38-4dc2-e676-fc939491a95a@gmail.com
Reported-by: Alexander Lakhin
This commit is contained in:
Jeff Davis
2024-03-24 16:28:34 -07:00
parent 3330a8d1b7
commit 503c0ad976
2 changed files with 101 additions and 6 deletions

View File

@@ -104,7 +104,7 @@ convert_case(char *dst, size_t dstsize, const char *src, ssize_t srclen,
size_t srcoff = 0;
size_t result_len = 0;
while (src[srcoff] != '\0' && (srclen < 0 || srcoff < srclen))
while ((srclen < 0 || srcoff < srclen) && src[srcoff] != '\0')
{
pg_wchar u1 = utf8_to_unicode((unsigned char *) src + srcoff);
int u1len = unicode_utf8len(u1);
@@ -115,7 +115,7 @@ convert_case(char *dst, size_t dstsize, const char *src, ssize_t srclen,
pg_wchar u2 = casemap->simplemap[casekind];
pg_wchar u2len = unicode_utf8len(u2);
if (result_len + u2len < dstsize)
if (result_len + u2len <= dstsize)
unicode_to_utf8(u2, (unsigned char *) dst + result_len);
result_len += u2len;
@@ -123,7 +123,7 @@ convert_case(char *dst, size_t dstsize, const char *src, ssize_t srclen,
else
{
/* no mapping; copy bytes from src */
if (result_len + u1len < dstsize)
if (result_len + u1len <= dstsize)
memcpy(dst + result_len, src + srcoff, u1len);
result_len += u1len;