summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2007-09-22 05:36:20 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2007-09-22 05:36:20 +0000
commit245dd2bca78762b5784fb9ec532c01d6e08334ce (patch)
tree677055b8ace1ad5b338be81c1c4ef32d490e3511
parent1aea75f047e44277e07742f950b85fe670a82d01 (diff)
downloadpostgresql-245dd2bca78762b5784fb9ec532c01d6e08334ce.tar.gz
Fix bogus calculation of potential output string length in translate().
-rw-r--r--src/backend/utils/adt/oracle_compat.c25
1 files changed, 15 insertions, 10 deletions
diff --git a/src/backend/utils/adt/oracle_compat.c b/src/backend/utils/adt/oracle_compat.c
index 48453c4ad6..17fcf4e20f 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.43 2002/09/04 20:31:28 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/oracle_compat.c,v 1.43.2.1 2007/09/22 05:36:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -682,27 +682,32 @@ 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;
+
+ /* check for integer overflow */
+ if (worst_len / pg_database_encoding_max_length() != m)
+ elog(ERROR, "requested length too large");
- source = VARDATA(string);
+ result = (text *) palloc(worst_len + VARHDRSZ);
target = VARDATA(result);
retlen = 0;