Skip to content

Commit b4d64a6

Browse files
committed
Remove our dependencies on MB_CUR_MAX in favor of believing that
pg_database_encoding_max_length() predicts the maximum character length returned by wchar2char(). Per Hiroshi Inoue, MB_CUR_MAX isn't usable on Windows because we allow encoding = UTF8 when the locale says differently; and getting rid of it seems a good idea on general principles because it narrows our dependence on libc's locale API just a little bit more. Also install a check for overflow of the buffer size computation.
1 parent 5f3724d commit b4d64a6

File tree

1 file changed

+34
-10
lines changed

1 file changed

+34
-10
lines changed

src/backend/utils/adt/formatting.c

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* -----------------------------------------------------------------------
22
* formatting.c
33
*
4-
* $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.151 2008/12/01 17:11:18 heikki Exp $
4+
* $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.152 2008/12/15 14:55:50 tgl Exp $
55
*
66
*
77
* Portions Copyright (c) 1999-2008, PostgreSQL Global Development Group
@@ -1461,7 +1461,14 @@ str_tolower(const char *buff, size_t nbytes)
14611461
if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c())
14621462
{
14631463
wchar_t *workspace;
1464-
int curr_char = 0;
1464+
size_t curr_char;
1465+
size_t result_size;
1466+
1467+
/* Overflow paranoia */
1468+
if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
1469+
ereport(ERROR,
1470+
(errcode(ERRCODE_OUT_OF_MEMORY),
1471+
errmsg("out of memory")));
14651472

14661473
/* Output workspace cannot have more codes than input bytes */
14671474
workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
@@ -1472,9 +1479,10 @@ str_tolower(const char *buff, size_t nbytes)
14721479
workspace[curr_char] = towlower(workspace[curr_char]);
14731480

14741481
/* Make result large enough; case change might change number of bytes */
1475-
result = palloc(curr_char * MB_CUR_MAX + 1);
1482+
result_size = curr_char * pg_database_encoding_max_length() + 1;
1483+
result = palloc(result_size);
14761484

1477-
wchar2char(result, workspace, curr_char * MB_CUR_MAX + 1);
1485+
wchar2char(result, workspace, result_size);
14781486
pfree(workspace);
14791487
}
14801488
else
@@ -1509,7 +1517,14 @@ str_toupper(const char *buff, size_t nbytes)
15091517
if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c())
15101518
{
15111519
wchar_t *workspace;
1512-
int curr_char = 0;
1520+
size_t curr_char;
1521+
size_t result_size;
1522+
1523+
/* Overflow paranoia */
1524+
if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
1525+
ereport(ERROR,
1526+
(errcode(ERRCODE_OUT_OF_MEMORY),
1527+
errmsg("out of memory")));
15131528

15141529
/* Output workspace cannot have more codes than input bytes */
15151530
workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
@@ -1520,9 +1535,10 @@ str_toupper(const char *buff, size_t nbytes)
15201535
workspace[curr_char] = towupper(workspace[curr_char]);
15211536

15221537
/* Make result large enough; case change might change number of bytes */
1523-
result = palloc(curr_char * MB_CUR_MAX + 1);
1538+
result_size = curr_char * pg_database_encoding_max_length() + 1;
1539+
result = palloc(result_size);
15241540

1525-
wchar2char(result, workspace, curr_char * MB_CUR_MAX + 1);
1541+
wchar2char(result, workspace, result_size);
15261542
pfree(workspace);
15271543
}
15281544
else
@@ -1558,7 +1574,14 @@ str_initcap(const char *buff, size_t nbytes)
15581574
if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c())
15591575
{
15601576
wchar_t *workspace;
1561-
int curr_char = 0;
1577+
size_t curr_char;
1578+
size_t result_size;
1579+
1580+
/* Overflow paranoia */
1581+
if ((nbytes + 1) > (INT_MAX / sizeof(wchar_t)))
1582+
ereport(ERROR,
1583+
(errcode(ERRCODE_OUT_OF_MEMORY),
1584+
errmsg("out of memory")));
15621585

15631586
/* Output workspace cannot have more codes than input bytes */
15641587
workspace = (wchar_t *) palloc((nbytes + 1) * sizeof(wchar_t));
@@ -1575,9 +1598,10 @@ str_initcap(const char *buff, size_t nbytes)
15751598
}
15761599

15771600
/* Make result large enough; case change might change number of bytes */
1578-
result = palloc(curr_char * MB_CUR_MAX + 1);
1601+
result_size = curr_char * pg_database_encoding_max_length() + 1;
1602+
result = palloc(result_size);
15791603

1580-
wchar2char(result, workspace, curr_char * MB_CUR_MAX + 1);
1604+
wchar2char(result, workspace, result_size);
15811605
pfree(workspace);
15821606
}
15831607
else

0 commit comments

Comments
 (0)