Skip to content

Commit 245dd2b

Browse files
committed
Fix bogus calculation of potential output string length in translate().
1 parent 1aea75f commit 245dd2b

File tree

1 file changed

+15
-10
lines changed

1 file changed

+15
-10
lines changed

src/backend/utils/adt/oracle_compat.c

+15-10
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/oracle_compat.c,v 1.43 2002/09/04 20:31:28 momjian Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/oracle_compat.c,v 1.43.2.1 2007/09/22 05:36:20 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -682,27 +682,32 @@ translate(PG_FUNCTION_ARGS)
682682
tolen,
683683
retlen,
684684
i;
685-
686-
int str_len;
687-
int estimate_len;
685+
int worst_len;
688686
int len;
689687
int source_len;
690688
int from_index;
691689

692-
if ((m = VARSIZE(string) - VARHDRSZ) <= 0)
690+
m = VARSIZE(string) - VARHDRSZ;
691+
if (m <= 0)
693692
PG_RETURN_TEXT_P(string);
693+
source = VARDATA(string);
694694

695695
fromlen = VARSIZE(from) - VARHDRSZ;
696696
from_ptr = VARDATA(from);
697697
tolen = VARSIZE(to) - VARHDRSZ;
698698
to_ptr = VARDATA(to);
699699

700-
str_len = VARSIZE(string);
701-
estimate_len = (tolen * 1.0 / fromlen + 0.5) * str_len;
702-
estimate_len = estimate_len > str_len ? estimate_len : str_len;
703-
result = (text *) palloc(estimate_len);
700+
/*
701+
* The worst-case expansion is to substitute a max-length character for
702+
* a single-byte character at each position of the string.
703+
*/
704+
worst_len = pg_database_encoding_max_length() * m;
705+
706+
/* check for integer overflow */
707+
if (worst_len / pg_database_encoding_max_length() != m)
708+
elog(ERROR, "requested length too large");
704709

705-
source = VARDATA(string);
710+
result = (text *) palloc(worst_len + VARHDRSZ);
706711
target = VARDATA(result);
707712
retlen = 0;
708713

0 commit comments

Comments
 (0)