Index: src/backend/lib/stringinfo.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/lib/stringinfo.c,v
retrieving revision 1.48
diff -p -u -c -r1.48 stringinfo.c
*** src/backend/lib/stringinfo.c	15 Nov 2007 21:14:35 -0000	1.48
--- src/backend/lib/stringinfo.c	23 Nov 2007 09:51:13 -0000
*************** appendStringInfo(StringInfo str, const c
*** 81,97 ****
  	{
  		va_list		args;
  		bool		success;
  
  		/* Try to format the data. */
  		va_start(args, fmt);
! 		success = appendStringInfoVA(str, fmt, args);
  		va_end(args);
  
  		if (success)
  			break;
  
  		/* Double the buffer size and try again. */
! 		enlargeStringInfo(str, str->maxlen);
  	}
  }
  
--- 81,98 ----
  	{
  		va_list		args;
  		bool		success;
+ 		int			needmore;
  
  		/* Try to format the data. */
  		va_start(args, fmt);
! 		success = appendStringInfoVA(str, fmt, args, &needmore);
  		va_end(args);
  
  		if (success)
  			break;
  
  		/* Double the buffer size and try again. */
! 		enlargeStringInfo(str, needmore);
  	}
  }
  
*************** appendStringInfo(StringInfo str, const c
*** 110,119 ****
   * that from here.
   */
  bool
! appendStringInfoVA(StringInfo str, const char *fmt, va_list args)
  {
  	int			avail,
! 				nprinted;
  
  	Assert(str != NULL);
  
--- 111,120 ----
   * that from here.
   */
  bool
! appendStringInfoVA(StringInfo str, const char *fmt, va_list args, int *needmore)
  {
  	int			avail,
! 				nprinted = 0;
  
  	Assert(str != NULL);
  
*************** appendStringInfoVA(StringInfo str, const
*** 123,129 ****
  	 */
  	avail = str->maxlen - str->len - 1;
  	if (avail < 16)
! 		return false;
  
  	/*
  	 * Assert check here is to catch buggy vsnprintf that overruns the
--- 124,130 ----
  	 */
  	avail = str->maxlen - str->len - 1;
  	if (avail < 16)
! 		goto no_room;
  
  	/*
  	 * Assert check here is to catch buggy vsnprintf that overruns the
*************** appendStringInfoVA(StringInfo str, const
*** 152,157 ****
--- 153,166 ----
  
  	/* Restore the trailing null so that str is unmodified. */
  	str->data[str->len] = '\0';
+ 
+ 	/*
+ 	 * Suggest how much more room is needed.  On systems with broken
+ 	 * vsnprintf() just double the buffer.
+ 	 */
+ no_room:
+ 	*needmore = (nprinted < str->maxlen) ? str->maxlen : nprinted + 1;
+ 
  	return false;
  }
  
Index: src/backend/utils/adt/xml.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/xml.c,v
retrieving revision 1.59
diff -p -u -c -r1.59 xml.c
*** src/backend/utils/adt/xml.c	20 Nov 2007 23:14:41 -0000	1.59
--- src/backend/utils/adt/xml.c	23 Nov 2007 09:51:13 -0000
*************** xml_errorHandler(void *ctxt, const char 
*** 1402,1418 ****
  	{
  		va_list		args;
  		bool		success;
  
  		/* Try to format the data. */
  		va_start(args, msg);
! 		success = appendStringInfoVA(xml_err_buf, msg, args);
  		va_end(args);
  
  		if (success)
  			break;
  
! 		/* Double the buffer size and try again. */
! 		enlargeStringInfo(xml_err_buf, xml_err_buf->maxlen);
  	}
  }
  
--- 1402,1419 ----
  	{
  		va_list		args;
  		bool		success;
+ 		int			needmore;
  
  		/* Try to format the data. */
  		va_start(args, msg);
! 		success = appendStringInfoVA(xml_err_buf, msg, args, &needmore);
  		va_end(args);
  
  		if (success)
  			break;
  
! 		/* Increase the buffer size and try again. */
! 		enlargeStringInfo(xml_err_buf, needmore);
  	}
  }
  
Index: src/backend/utils/error/elog.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/error/elog.c,v
retrieving revision 1.198
diff -p -u -c -r1.198 elog.c
*** src/backend/utils/error/elog.c	15 Nov 2007 21:14:40 -0000	1.198
--- src/backend/utils/error/elog.c	23 Nov 2007 09:51:13 -0000
*************** errcode_for_socket_access(void)
*** 610,621 ****
  		{ \
  			va_list		args; \
  			bool		success; \
  			va_start(args, fmt); \
! 			success = appendStringInfoVA(&buf, fmtbuf, args); \
  			va_end(args); \
  			if (success) \
  				break; \
! 			enlargeStringInfo(&buf, buf.maxlen); \
  		} \
  		/* Done with expanded fmt */ \
  		pfree(fmtbuf); \
--- 610,622 ----
  		{ \
  			va_list		args; \
  			bool		success; \
+ 			int			needmore; \
  			va_start(args, fmt); \
! 			success = appendStringInfoVA(&buf, fmtbuf, args, &needmore); \
  			va_end(args); \
  			if (success) \
  				break; \
! 			enlargeStringInfo(&buf, needmore); \
  		} \
  		/* Done with expanded fmt */ \
  		pfree(fmtbuf); \
Index: src/include/lib/stringinfo.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/lib/stringinfo.h,v
retrieving revision 1.34
diff -p -u -c -r1.34 stringinfo.h
*** src/include/lib/stringinfo.h	3 Mar 2007 19:32:55 -0000	1.34
--- src/include/lib/stringinfo.h	23 Nov 2007 09:51:13 -0000
*************** __attribute__((format(printf, 2, 3)));
*** 105,111 ****
   * without modifying str.  Typically the caller would enlarge str and retry
   * on false return --- see appendStringInfo for standard usage pattern.
   */
! extern bool appendStringInfoVA(StringInfo str, const char *fmt, va_list args);
  
  /*------------------------
   * appendStringInfoString
--- 105,111 ----
   * without modifying str.  Typically the caller would enlarge str and retry
   * on false return --- see appendStringInfo for standard usage pattern.
   */
! extern bool appendStringInfoVA(StringInfo str, const char *fmt, va_list args, int *needmore);
  
  /*------------------------
   * appendStringInfoString
Index: src/pl/plpython/plpython.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/pl/plpython/plpython.c,v
retrieving revision 1.105
diff -p -u -c -r1.105 plpython.c
*** src/pl/plpython/plpython.c	23 Nov 2007 01:46:34 -0000	1.105
--- src/pl/plpython/plpython.c	23 Nov 2007 09:51:14 -0000
*************** PLy_elog(int elevel, const char *fmt,...
*** 2908,2920 ****
  	{
  		va_list		ap;
  		bool		success;
  
  		va_start(ap, fmt);
! 		success = appendStringInfoVA(&emsg, fmt, ap);
  		va_end(ap);
  		if (success)
  			break;
! 		enlargeStringInfo(&emsg, emsg.maxlen);
  	}
  
  	PG_TRY();
--- 2908,2921 ----
  	{
  		va_list		ap;
  		bool		success;
+ 		int			needmore;
  
  		va_start(ap, fmt);
! 		success = appendStringInfoVA(&emsg, fmt, ap, &needmore);
  		va_end(ap);
  		if (success)
  			break;
! 		enlargeStringInfo(&emsg, needmore);
  	}
  
  	PG_TRY();
