Skip to content

Commit bbda96d

Browse files
committed
Fix bogus calculation of potential output string length in translate().
1 parent 571340a commit bbda96d

File tree

1 file changed

+17
-13
lines changed

1 file changed

+17
-13
lines changed

src/backend/utils/adt/oracle_compat.c

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/utils/adt/oracle_compat.c,v 1.72 2007/09/21 22:52:52 tgl Exp $
12+
* $PostgreSQL: pgsql/src/backend/utils/adt/oracle_compat.c,v 1.73 2007/09/22 05:35:42 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -1162,30 +1162,34 @@ translate(PG_FUNCTION_ARGS)
11621162
tolen,
11631163
retlen,
11641164
i;
1165-
1166-
int str_len;
1167-
int estimate_len;
1165+
int worst_len;
11681166
int len;
11691167
int source_len;
11701168
int from_index;
11711169

11721170
m = VARSIZE_ANY_EXHDR(string);
1173-
11741171
if (m <= 0)
11751172
PG_RETURN_TEXT_P(string);
1173+
source = VARDATA_ANY(string);
11761174

11771175
fromlen = VARSIZE_ANY_EXHDR(from);
11781176
from_ptr = VARDATA_ANY(from);
11791177
tolen = VARSIZE_ANY_EXHDR(to);
11801178
to_ptr = VARDATA_ANY(to);
11811179

1182-
str_len = VARSIZE_ANY_EXHDR(string);
1183-
source = VARDATA_ANY(string);
1180+
/*
1181+
* The worst-case expansion is to substitute a max-length character for
1182+
* a single-byte character at each position of the string.
1183+
*/
1184+
worst_len = pg_database_encoding_max_length() * m;
11841185

1185-
estimate_len = (tolen * 1.0 / fromlen + 0.5) * str_len;
1186-
estimate_len = estimate_len > str_len ? estimate_len : str_len;
1186+
/* check for integer overflow */
1187+
if (worst_len / pg_database_encoding_max_length() != m)
1188+
ereport(ERROR,
1189+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1190+
errmsg("requested length too large")));
11871191

1188-
result = (text *) palloc(estimate_len + VARHDRSZ);
1192+
result = (text *) palloc(worst_len + VARHDRSZ);
11891193
target = VARDATA(result);
11901194
retlen = 0;
11911195

@@ -1238,9 +1242,9 @@ translate(PG_FUNCTION_ARGS)
12381242
SET_VARSIZE(result, retlen + VARHDRSZ);
12391243

12401244
/*
1241-
* There may be some wasted space in the result if deletions occurred, but
1242-
* it's not worth reallocating it; the function result probably won't live
1243-
* long anyway.
1245+
* The function result is probably much bigger than needed, if we're
1246+
* using a multibyte encoding, but it's not worth reallocating it;
1247+
* the result probably won't live long anyway.
12441248
*/
12451249

12461250
PG_RETURN_TEXT_P(result);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy