From 558c9270c4b25121342e192aca96185140ed164f Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Fri, 23 Nov 2007 01:46:34 +0000
Subject: [PATCH] Fix buggy usage of vsnprintf in PL/Python by removing it
 altogether, instead relying on stringinfo.c.  This fixes a problem reported
 by Marko Kreen, but I didn't use his patch, per subsequent discussion.

---
 src/pl/plpython/plpython.c | 99 ++++++++++----------------------------
 1 file changed, 26 insertions(+), 73 deletions(-)

diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c
index 80ce24caef7..2b6e49d47be 100644
--- a/src/pl/plpython/plpython.c
+++ b/src/pl/plpython/plpython.c
@@ -1,7 +1,7 @@
 /**********************************************************************
  * plpython.c - python as a procedural language for PostgreSQL
  *
- *	$PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.104 2007/11/15 21:14:46 momjian Exp $
+ *	$PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.105 2007/11/23 01:46:34 alvherre Exp $
  *
  *********************************************************************
  */
@@ -210,11 +210,8 @@ static char *PLy_procedure_name(PLyProcedure *);
 /* some utility functions */
 static void PLy_elog(int, const char *,...);
 static char *PLy_traceback(int *);
-static char *PLy_vprintf(const char *fmt, va_list ap);
-static char *PLy_printf(const char *fmt,...);
 
 static void *PLy_malloc(size_t);
-static void *PLy_realloc(void *, size_t);
 static char *PLy_strdup(const char *);
 static void PLy_free(void *);
 
@@ -2900,35 +2897,44 @@ PLy_exception_set(PyObject * exc, const char *fmt,...)
 static void
 PLy_elog(int elevel, const char *fmt,...)
 {
-	va_list		ap;
-	char	   *xmsg,
-			   *emsg;
+	char	   *xmsg;
 	int			xlevel;
+	StringInfoData emsg;
 
 	xmsg = PLy_traceback(&xlevel);
 
-	va_start(ap, fmt);
-	emsg = PLy_vprintf(fmt, ap);
-	va_end(ap);
+	initStringInfo(&emsg);
+	for (;;)
+	{
+		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();
 	{
 		ereport(elevel,
-				(errmsg("plpython: %s", emsg),
+				(errmsg("plpython: %s", emsg.data),
 				 (xmsg) ? errdetail("%s", xmsg) : 0));
 	}
 	PG_CATCH();
 	{
-		PLy_free(emsg);
+		pfree(emsg.data);
 		if (xmsg)
-			PLy_free(xmsg);
+			pfree(xmsg);
 		PG_RE_THROW();
 	}
 	PG_END_TRY();
 
-	PLy_free(emsg);
+	pfree(emsg.data);
 	if (xmsg)
-		PLy_free(xmsg);
+		pfree(xmsg);
 }
 
 static char *
@@ -2940,8 +2946,8 @@ PLy_traceback(int *xlevel)
 	PyObject   *eob,
 			   *vob = NULL;
 	char	   *vstr,
-			   *estr,
-			   *xstr = NULL;
+			   *estr;
+	StringInfoData xstr;
 
 	/*
 	 * get the current exception
@@ -2973,7 +2979,8 @@ PLy_traceback(int *xlevel)
 	 * Assert() be more appropriate?
 	 */
 	estr = eob ? PyString_AsString(eob) : "Unknown Exception";
-	xstr = PLy_printf("%s: %s", estr, vstr);
+	initStringInfo(&xstr);
+	appendStringInfo(&xstr, "%s: %s", estr, vstr);
 
 	Py_DECREF(eob);
 	Py_XDECREF(vob);
@@ -2990,49 +2997,7 @@ PLy_traceback(int *xlevel)
 		*xlevel = ERROR;
 
 	Py_DECREF(e);
-	return xstr;
-}
-
-static char *
-PLy_printf(const char *fmt,...)
-{
-	va_list		ap;
-	char	   *emsg;
-
-	va_start(ap, fmt);
-	emsg = PLy_vprintf(fmt, ap);
-	va_end(ap);
-	return emsg;
-}
-
-static char *
-PLy_vprintf(const char *fmt, va_list ap)
-{
-	size_t		blen;
-	int			bchar,
-				tries = 2;
-	char	   *buf;
-
-	blen = strlen(fmt) * 2;
-	if (blen < 256)
-		blen = 256;
-	buf = PLy_malloc(blen * sizeof(char));
-
-	while (1)
-	{
-		bchar = vsnprintf(buf, blen, fmt, ap);
-		if (bchar > 0 && bchar < blen)
-			return buf;
-		if (tries-- <= 0)
-			break;
-		if (blen > 0)
-			blen = bchar + 1;
-		else
-			blen *= 2;
-		buf = PLy_realloc(buf, blen);
-	}
-	PLy_free(buf);
-	return NULL;
+	return xstr.data;
 }
 
 /* python module code */
@@ -3050,18 +3015,6 @@ PLy_malloc(size_t bytes)
 	return ptr;
 }
 
-static void *
-PLy_realloc(void *optr, size_t bytes)
-{
-	void	   *nptr = realloc(optr, bytes);
-
-	if (nptr == NULL)
-		ereport(FATAL,
-				(errcode(ERRCODE_OUT_OF_MEMORY),
-				 errmsg("out of memory")));
-	return nptr;
-}
-
 static char *
 PLy_strdup(const char *str)
 {
-- 
GitLab