mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	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.
This commit is contained in:
		@@ -29,7 +29,7 @@
 | 
				
			|||||||
 * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 | 
					 * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *	$PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.66.2.4 2006/02/20 20:10:41 neilc Exp $
 | 
					 *	$PostgreSQL: pgsql/src/pl/plpython/plpython.c,v 1.66.2.5 2007/11/23 01:47:12 alvherre Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *********************************************************************
 | 
					 *********************************************************************
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -48,6 +48,7 @@
 | 
				
			|||||||
#include "commands/trigger.h"
 | 
					#include "commands/trigger.h"
 | 
				
			||||||
#include "executor/spi.h"
 | 
					#include "executor/spi.h"
 | 
				
			||||||
#include "fmgr.h"
 | 
					#include "fmgr.h"
 | 
				
			||||||
 | 
					#include "lib/stringinfo.h"
 | 
				
			||||||
#include "nodes/makefuncs.h"
 | 
					#include "nodes/makefuncs.h"
 | 
				
			||||||
#include "parser/parse_type.h"
 | 
					#include "parser/parse_type.h"
 | 
				
			||||||
#include "tcop/tcopprot.h"
 | 
					#include "tcop/tcopprot.h"
 | 
				
			||||||
@@ -204,11 +205,8 @@ static char *PLy_procedure_name(PLyProcedure *);
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
static void PLy_elog(int, const char *,...);
 | 
					static void PLy_elog(int, const char *,...);
 | 
				
			||||||
static char *PLy_traceback(int *);
 | 
					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_malloc(size_t);
 | 
				
			||||||
static void *PLy_realloc(void *, size_t);
 | 
					 | 
				
			||||||
static void PLy_free(void *);
 | 
					static void PLy_free(void *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* sub handlers for functions and triggers
 | 
					/* sub handlers for functions and triggers
 | 
				
			||||||
@@ -2478,35 +2476,44 @@ PLy_exception_set(PyObject * exc, const char *fmt,...)
 | 
				
			|||||||
static void
 | 
					static void
 | 
				
			||||||
PLy_elog(int elevel, const char *fmt,...)
 | 
					PLy_elog(int elevel, const char *fmt,...)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	va_list		ap;
 | 
						char	   *xmsg;
 | 
				
			||||||
	char	   *xmsg,
 | 
					 | 
				
			||||||
			   *emsg;
 | 
					 | 
				
			||||||
	int			xlevel;
 | 
						int			xlevel;
 | 
				
			||||||
 | 
						StringInfoData emsg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	xmsg = PLy_traceback(&xlevel);
 | 
						xmsg = PLy_traceback(&xlevel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						initStringInfo(&emsg);
 | 
				
			||||||
 | 
						for (;;)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							va_list		ap;
 | 
				
			||||||
 | 
							bool		success;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		va_start(ap, fmt);
 | 
							va_start(ap, fmt);
 | 
				
			||||||
	emsg = PLy_vprintf(fmt, ap);
 | 
							success = appendStringInfoVA(&emsg, fmt, ap);
 | 
				
			||||||
		va_end(ap);
 | 
							va_end(ap);
 | 
				
			||||||
 | 
							if (success)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							enlargeStringInfo(&emsg, emsg.maxlen);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	PG_TRY();
 | 
						PG_TRY();
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		ereport(elevel,
 | 
							ereport(elevel,
 | 
				
			||||||
				(errmsg("plpython: %s", emsg),
 | 
									(errmsg("plpython: %s", emsg.data),
 | 
				
			||||||
				 (xmsg) ? errdetail("%s", xmsg) : 0));
 | 
									 (xmsg) ? errdetail("%s", xmsg) : 0));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	PG_CATCH();
 | 
						PG_CATCH();
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		PLy_free(emsg);
 | 
							pfree(emsg.data);
 | 
				
			||||||
		if (xmsg)
 | 
							if (xmsg)
 | 
				
			||||||
			PLy_free(xmsg);
 | 
								pfree(xmsg);
 | 
				
			||||||
		PG_RE_THROW();
 | 
							PG_RE_THROW();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	PG_END_TRY();
 | 
						PG_END_TRY();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	PLy_free(emsg);
 | 
						pfree(emsg.data);
 | 
				
			||||||
	if (xmsg)
 | 
						if (xmsg)
 | 
				
			||||||
		PLy_free(xmsg);
 | 
							pfree(xmsg);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static char *
 | 
					static char *
 | 
				
			||||||
@@ -2518,8 +2525,8 @@ PLy_traceback(int *xlevel)
 | 
				
			|||||||
	PyObject   *eob,
 | 
						PyObject   *eob,
 | 
				
			||||||
			   *vob = NULL;
 | 
								   *vob = NULL;
 | 
				
			||||||
	char	   *vstr,
 | 
						char	   *vstr,
 | 
				
			||||||
			   *estr,
 | 
								   *estr;
 | 
				
			||||||
			   *xstr = NULL;
 | 
						StringInfoData xstr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * get the current exception
 | 
						 * get the current exception
 | 
				
			||||||
@@ -2551,7 +2558,8 @@ PLy_traceback(int *xlevel)
 | 
				
			|||||||
	 * Assert() be more appropriate?
 | 
						 * Assert() be more appropriate?
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	estr = eob ? PyString_AsString(eob) : "Unknown Exception";
 | 
						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_DECREF(eob);
 | 
				
			||||||
	Py_XDECREF(vob);
 | 
						Py_XDECREF(vob);
 | 
				
			||||||
@@ -2568,49 +2576,7 @@ PLy_traceback(int *xlevel)
 | 
				
			|||||||
		*xlevel = ERROR;
 | 
							*xlevel = ERROR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Py_DECREF(e);
 | 
						Py_DECREF(e);
 | 
				
			||||||
	return xstr;
 | 
						return xstr.data;
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* python module code
 | 
					/* python module code
 | 
				
			||||||
@@ -2632,18 +2598,6 @@ PLy_malloc(size_t bytes)
 | 
				
			|||||||
	return ptr;
 | 
						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;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* define this away
 | 
					/* define this away
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user