diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2007-09-22 05:36:14 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2007-09-22 05:36:14 +0000 |
commit | a51302deb3d0df960dcce6feb165991d5ab0290f (patch) | |
tree | eb560e65a4495611a2f7858aeb99364ef5b4a53b /src/backend/utils/adt/oracle_compat.c | |
parent | 0a3b51efa02a8facb55ad41b58d80201e967c257 (diff) | |
download | postgresql-a51302deb3d0df960dcce6feb165991d5ab0290f.tar.gz postgresql-a51302deb3d0df960dcce6feb165991d5ab0290f.zip |
Fix bogus calculation of potential output string length in translate().
Diffstat (limited to 'src/backend/utils/adt/oracle_compat.c')
-rw-r--r-- | src/backend/utils/adt/oracle_compat.c | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/src/backend/utils/adt/oracle_compat.c b/src/backend/utils/adt/oracle_compat.c index cd9ad553c3d..27f053b34db 100644 --- a/src/backend/utils/adt/oracle_compat.c +++ b/src/backend/utils/adt/oracle_compat.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/oracle_compat.c,v 1.48 2003/08/08 21:42:06 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/oracle_compat.c,v 1.48.4.1 2007/09/22 05:36:14 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -750,27 +750,34 @@ translate(PG_FUNCTION_ARGS) tolen, retlen, i; - - int str_len; - int estimate_len; + int worst_len; int len; int source_len; int from_index; - if ((m = VARSIZE(string) - VARHDRSZ) <= 0) + m = VARSIZE(string) - VARHDRSZ; + if (m <= 0) PG_RETURN_TEXT_P(string); + source = VARDATA(string); fromlen = VARSIZE(from) - VARHDRSZ; from_ptr = VARDATA(from); tolen = VARSIZE(to) - VARHDRSZ; to_ptr = VARDATA(to); - str_len = VARSIZE(string); - estimate_len = (tolen * 1.0 / fromlen + 0.5) * str_len; - estimate_len = estimate_len > str_len ? estimate_len : str_len; - result = (text *) palloc(estimate_len); + /* + * The worst-case expansion is to substitute a max-length character for + * a single-byte character at each position of the string. + */ + worst_len = pg_database_encoding_max_length() * m; - source = VARDATA(string); + /* check for integer overflow */ + if (worst_len / pg_database_encoding_max_length() != m) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("requested length too large"))); + + result = (text *) palloc(worst_len + VARHDRSZ); target = VARDATA(result); retlen = 0; |