Fix bogus calculation of potential output string length in translate().
authorTom Lane <[email protected]>
Sat, 22 Sep 2007 05:36:20 +0000 (05:36 +0000)
committerTom Lane <[email protected]>
Sat, 22 Sep 2007 05:36:20 +0000 (05:36 +0000)
src/backend/utils/adt/oracle_compat.c

index 48453c4ad6b578bfa9f6852d48954000545aeb06..17fcf4e20f8323435343828b725650ea5c52a746 100644 (file)
@@ -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;