diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 6095a1f4fdc0091557c45a1974f1c181f111c61f..0b54f72e6e0eb2d0736794563e80b95c0c8bc301 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------
  * formatting.c
  *
- * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.129 2007/02/27 23:48:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.130 2007/06/29 01:51:35 tgl Exp $
  *
  *
  *	 Portions Copyright (c) 1999-2007, PostgreSQL Global Development Group
@@ -74,6 +74,7 @@
 #include <unistd.h>
 #include <math.h>
 #include <float.h>
+#include <limits.h>
 #include <locale.h>
 
 #include "utils/builtins.h"
@@ -112,8 +113,8 @@
  * More is in float.c
  * ----------
  */
-#define MAXFLOATWIDTH	64
-#define MAXDOUBLEWIDTH	128
+#define MAXFLOATWIDTH	60
+#define MAXDOUBLEWIDTH	500
 
 
 /* ----------
@@ -958,13 +959,12 @@ static char *localize_month(int index);
 static char *localize_day_full(int index);
 static char *localize_day(int index);
 
-/*
- * External (defined in oracle_compat.c 
- */
 #if defined(HAVE_WCSTOMBS) && defined(HAVE_TOWLOWER)
 #define USE_WIDE_UPPER_LOWER
+/* externs are in oracle_compat.c */
 extern char *wstring_upper(char *str);
 extern char *wstring_lower(char *str);
+
 static char *localized_str_toupper(char *buff);
 static char *localized_str_tolower(char *buff);
 #else
@@ -1510,7 +1510,7 @@ str_numth(char *dest, char *num, int type)
 }
 
 /* ----------
- * Convert string to upper-string. Input string is modified in place.
+ * Convert string to upper case. Input string is modified in place.
  * ----------
  */
 static char *
@@ -1531,7 +1531,7 @@ str_toupper(char *buff)
 }
 
 /* ----------
- * Convert string to lower-string. Input string is modified in place.
+ * Convert string to lower case. Input string is modified in place.
  * ----------
  */
 static char *
@@ -1553,7 +1553,8 @@ str_tolower(char *buff)
 
 #ifdef USE_WIDE_UPPER_LOWER
 /* ----------
- * Convert localized string to upper string. Input string is modified in place.
+ * Convert localized string to upper case.
+ * Input string may be modified in place ... or we might make a copy.
  * ----------
  */
 static char *
@@ -1579,7 +1580,8 @@ localized_str_toupper(char *buff)
 }
 
 /* ----------
- * Convert localized string to upper string. Input string is modified in place.
+ * Convert localized string to lower case.
+ * Input string may be modified in place ... or we might make a copy.
  * ----------
  */
 static char *
@@ -2107,19 +2109,16 @@ dch_time(int arg, char *inout, int suf, bool is_to_char, bool is_interval,
 			INVALID_FOR_INTERVAL;
 			if (is_to_char && tmtcTzn(tmtc))
 			{
-				int			siz = strlen(tmtcTzn(tmtc));
-
 				if (arg == DCH_TZ)
 					strcpy(inout, tmtcTzn(tmtc));
 				else
 				{
-					char	   *p = palloc(siz);
+					char	   *p = pstrdup(tmtcTzn(tmtc));
 
-					strcpy(p, tmtcTzn(tmtc));
 					strcpy(inout, str_tolower(p));
 					pfree(p);
 				}
-				return siz;
+				return strlen(inout);
 			}
 			else if (!is_to_char)
 				ereport(ERROR,
@@ -3624,7 +3623,7 @@ static char *
 fill_str(char *str, int c, int max)
 {
 	memset(str, c, max);
-	*(str + max + 1) = '\0';
+	*(str + max) = '\0';
 	return str;
 }
 
@@ -4798,10 +4797,9 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
 #define NUM_TOCHAR_prepare \
 do { \
 	len = VARSIZE(fmt) - VARHDRSZ;					\
-	if (len <= 0)							\
+	if (len <= 0 || len >= (INT_MAX-VARHDRSZ)/NUM_MAX_ITEM_SIZ)		\
 		return DirectFunctionCall1(textin, CStringGetDatum(""));	\
-	result	= (text *) palloc( (len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ); \
-	memset(result, 0,  (len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ ); \
+	result	= (text *) palloc0((len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ);	\
 	format	= NUM_cache(len, &Num, VARDATA(fmt), &shouldFree);		\
 } while (0)
 
@@ -4811,30 +4809,19 @@ do { \
  */
 #define NUM_TOCHAR_finish \
 do { \
-	NUM_processor(format, &Num, VARDATA(result),			\
-		numstr, plen, sign, true);				\
-	pfree(orgnum);							\
+	NUM_processor(format, &Num, VARDATA(result), numstr, plen, sign, true);	\
 									\
-	if (shouldFree)							\
-		pfree(format);						\
+	if (shouldFree)					\
+		pfree(format);				\
 									\
-	/*
-	 * for result is allocated max memory, which current format-picture\
-	 * needs, now it must be re-allocate to result real size	\
+	/*								\
+	 * Convert null-terminated representation of result to standard text. \
+	 * The result is usually much bigger than it needs to be, but there \
+	 * seems little point in realloc'ing it smaller. \
 	 */								\
-	if (!(len = strlen(VARDATA(result))))				\
-	{								\
-		pfree(result);						\
-		PG_RETURN_NULL();					\
-	}								\
-									\
-	result_tmp	= result;					\
-	result		= (text *) palloc(len + VARHDRSZ);		\
-									\
-	memcpy(VARDATA(result), VARDATA(result_tmp), len);	\
-	SET_VARSIZE(result, len + VARHDRSZ);				\
-	pfree(result_tmp);						\
-} while(0)
+	len = strlen(VARDATA(result));	\
+	SET_VARSIZE(result, len + VARHDRSZ); \
+} while (0)
 
 /* -------------------
  * NUMERIC to_number() (convert string to numeric)
@@ -4856,7 +4843,7 @@ numeric_to_number(PG_FUNCTION_ARGS)
 
 	len = VARSIZE(fmt) - VARHDRSZ;
 
-	if (len <= 0)
+	if (len <= 0 || len >= INT_MAX/NUM_MAX_ITEM_SIZ)
 		PG_RETURN_NULL();
 
 	format = NUM_cache(len, &Num, VARDATA(fmt), &shouldFree);
@@ -4891,8 +4878,7 @@ numeric_to_char(PG_FUNCTION_ARGS)
 	text	   *fmt = PG_GETARG_TEXT_P(1);
 	NUMDesc		Num;
 	FormatNode *format;
-	text	   *result,
-			   *result_tmp;
+	text	   *result;
 	bool		shouldFree;
 	int			len = 0,
 				plen = 0,
@@ -4915,7 +4901,6 @@ numeric_to_char(PG_FUNCTION_ARGS)
 		numstr = orgnum =
 			int_to_roman(DatumGetInt32(DirectFunctionCall1(numeric_int4,
 													   NumericGetDatum(x))));
-		pfree(x);
 	}
 	else
 	{
@@ -4934,9 +4919,6 @@ numeric_to_char(PG_FUNCTION_ARGS)
 			val = DatumGetNumeric(DirectFunctionCall2(numeric_mul,
 													  NumericGetDatum(value),
 													  NumericGetDatum(x)));
-			pfree(x);
-			pfree(a);
-			pfree(b);
 			Num.pre += Num.multi;
 		}
 
@@ -4945,10 +4927,9 @@ numeric_to_char(PG_FUNCTION_ARGS)
 												Int32GetDatum(Num.post)));
 		orgnum = DatumGetCString(DirectFunctionCall1(numeric_out,
 													 NumericGetDatum(x)));
-		pfree(x);
 
 		if (*orgnum == '-')
-		{						/* < 0 */
+		{
 			sign = '-';
 			numstr = orgnum + 1;
 		}
@@ -4966,13 +4947,10 @@ numeric_to_char(PG_FUNCTION_ARGS)
 			plen = Num.pre - len;
 		else if (len > Num.pre)
 		{
-			fill_str(numstr, '#', Num.pre);
+			numstr = (char *) palloc(Num.pre + Num.post + 2);
+			fill_str(numstr, '#', Num.pre + Num.post + 1);
 			*(numstr + Num.pre) = '.';
-			fill_str(numstr + 1 + Num.pre, '#', Num.post);
 		}
-
-		if (IS_MULTI(&Num))
-			pfree(val);
 	}
 
 	NUM_TOCHAR_finish;
@@ -4990,8 +4968,7 @@ int4_to_char(PG_FUNCTION_ARGS)
 	text	   *fmt = PG_GETARG_TEXT_P(1);
 	NUMDesc		Num;
 	FormatNode *format;
-	text	   *result,
-			   *result_tmp;
+	text	   *result;
 	bool		shouldFree;
 	int			len = 0,
 				plen = 0,
@@ -5019,40 +4996,34 @@ int4_to_char(PG_FUNCTION_ARGS)
 			orgnum = DatumGetCString(DirectFunctionCall1(int4out,
 													  Int32GetDatum(value)));
 		}
-		len = strlen(orgnum);
 
 		if (*orgnum == '-')
-		{						/* < 0 */
+		{
 			sign = '-';
-			--len;
+			orgnum++;
 		}
 		else
 			sign = '+';
+		len = strlen(orgnum);
 
 		if (Num.post)
 		{
-			int			i;
-
 			numstr = (char *) palloc(len + Num.post + 2);
-			strcpy(numstr, orgnum + (*orgnum == '-' ? 1 : 0));
+			strcpy(numstr, orgnum);
 			*(numstr + len) = '.';
-
-			for (i = len + 1; i <= len + Num.post; i++)
-				*(numstr + i) = '0';
+			memset(numstr + len + 1, '0', Num.post);
 			*(numstr + len + Num.post + 1) = '\0';
-			pfree(orgnum);
-			orgnum = numstr;
 		}
 		else
-			numstr = orgnum + (*orgnum == '-' ? 1 : 0);
+			numstr = orgnum;
 
 		if (Num.pre > len)
 			plen = Num.pre - len;
 		else if (len > Num.pre)
 		{
-			fill_str(numstr, '#', Num.pre);
+			numstr = (char *) palloc(Num.pre + Num.post + 2);
+			fill_str(numstr, '#', Num.pre + Num.post + 1);
 			*(numstr + Num.pre) = '.';
-			fill_str(numstr + 1 + Num.pre, '#', Num.post);
 		}
 	}
 
@@ -5071,8 +5042,7 @@ int8_to_char(PG_FUNCTION_ARGS)
 	text	   *fmt = PG_GETARG_TEXT_P(1);
 	NUMDesc		Num;
 	FormatNode *format;
-	text	   *result,
-			   *result_tmp;
+	text	   *result;
 	bool		shouldFree;
 	int			len = 0,
 				plen = 0,
@@ -5106,40 +5076,34 @@ int8_to_char(PG_FUNCTION_ARGS)
 
 		orgnum = DatumGetCString(DirectFunctionCall1(int8out,
 													 Int64GetDatum(value)));
-		len = strlen(orgnum);
 
 		if (*orgnum == '-')
-		{						/* < 0 */
+		{
 			sign = '-';
-			--len;
+			orgnum++;
 		}
 		else
 			sign = '+';
+		len = strlen(orgnum);
 
 		if (Num.post)
 		{
-			int			i;
-
 			numstr = (char *) palloc(len + Num.post + 2);
-			strcpy(numstr, orgnum + (*orgnum == '-' ? 1 : 0));
+			strcpy(numstr, orgnum);
 			*(numstr + len) = '.';
-
-			for (i = len + 1; i <= len + Num.post; i++)
-				*(numstr + i) = '0';
+			memset(numstr + len + 1, '0', Num.post);
 			*(numstr + len + Num.post + 1) = '\0';
-			pfree(orgnum);
-			orgnum = numstr;
 		}
 		else
-			numstr = orgnum + (*orgnum == '-' ? 1 : 0);
+			numstr = orgnum;
 
 		if (Num.pre > len)
 			plen = Num.pre - len;
 		else if (len > Num.pre)
 		{
-			fill_str(numstr, '#', Num.pre);
+			numstr = (char *) palloc(Num.pre + Num.post + 2);
+			fill_str(numstr, '#', Num.pre + Num.post + 1);
 			*(numstr + Num.pre) = '.';
-			fill_str(numstr + 1 + Num.pre, '#', Num.post);
 		}
 	}
 
@@ -5158,8 +5122,7 @@ float4_to_char(PG_FUNCTION_ARGS)
 	text	   *fmt = PG_GETARG_TEXT_P(1);
 	NUMDesc		Num;
 	FormatNode *format;
-	text	   *result,
-			   *result_tmp;
+	text	   *result;
 	bool		shouldFree;
 	int			len = 0,
 				plen = 0,
@@ -5214,9 +5177,9 @@ float4_to_char(PG_FUNCTION_ARGS)
 			plen = Num.pre - len;
 		else if (len > Num.pre)
 		{
-			fill_str(numstr, '#', Num.pre);
+			numstr = (char *) palloc(Num.pre + Num.post + 2);
+			fill_str(numstr, '#', Num.pre + Num.post + 1);
 			*(numstr + Num.pre) = '.';
-			fill_str(numstr + 1 + Num.pre, '#', Num.post);
 		}
 	}
 
@@ -5235,8 +5198,7 @@ float8_to_char(PG_FUNCTION_ARGS)
 	text	   *fmt = PG_GETARG_TEXT_P(1);
 	NUMDesc		Num;
 	FormatNode *format;
-	text	   *result,
-			   *result_tmp;
+	text	   *result;
 	bool		shouldFree;
 	int			len = 0,
 				plen = 0,
@@ -5289,9 +5251,9 @@ float8_to_char(PG_FUNCTION_ARGS)
 			plen = Num.pre - len;
 		else if (len > Num.pre)
 		{
-			fill_str(numstr, '#', Num.pre);
+			numstr = (char *) palloc(Num.pre + Num.post + 2);
+			fill_str(numstr, '#', Num.pre + Num.post + 1);
 			*(numstr + Num.pre) = '.';
-			fill_str(numstr + 1 + Num.pre, '#', Num.post);
 		}
 	}