From: Tom Lane Date: Sat, 22 Sep 2007 05:36:07 +0000 (+0000) Subject: Fix bogus calculation of potential output string length in translate(). X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=a6fe13c63d86e54d5d63a845f923f932f778b91b;p=users%2Fbernd%2Fpostgres.git Fix bogus calculation of potential output string length in translate(). --- diff --git a/src/backend/utils/adt/oracle_compat.c b/src/backend/utils/adt/oracle_compat.c index f03e9274f8..b62df32e56 100644 --- a/src/backend/utils/adt/oracle_compat.c +++ b/src/backend/utils/adt/oracle_compat.c @@ -29,6 +29,7 @@ #endif #include "utils/builtins.h" +#include "utils/pg_locale.h" #include "mb/pg_wchar.h" @@ -166,8 +167,8 @@ Datum lower(PG_FUNCTION_ARGS) { #ifdef USE_WIDE_UPPER_LOWER - /* use wide char code only when max encoding length > one */ - if (pg_database_encoding_max_length() > 1) + /* use wide char code only when max encoding length > 1 and ctype != C */ + if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c()) { text *string = PG_GETARG_TEXT_P(0); text *result; @@ -228,8 +229,8 @@ Datum upper(PG_FUNCTION_ARGS) { #ifdef USE_WIDE_UPPER_LOWER - /* use wide char code only when max encoding length > one */ - if (pg_database_encoding_max_length() > 1) + /* use wide char code only when max encoding length > 1 and ctype != C */ + if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c()) { text *string = PG_GETARG_TEXT_P(0); text *result; @@ -293,8 +294,8 @@ Datum initcap(PG_FUNCTION_ARGS) { #ifdef USE_WIDE_UPPER_LOWER - /* use wide char code only when max encoding length > one */ - if (pg_database_encoding_max_length() > 1) + /* use wide char code only when max encoding length > 1 and ctype != C */ + if (pg_database_encoding_max_length() > 1 && !lc_ctype_is_c()) { text *string = PG_GETARG_TEXT_P(0); text *result; @@ -955,27 +956,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;