From d289da2c1691ce1e8b6ca1320e2c460e84cb64d8 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Fri, 23 Nov 2007 01:48:08 +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 | 100 ++++++++++--------------------------- 1 file changed, 27 insertions(+), 73 deletions(-) diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c index e811776599e..f765a685cae 100644 --- a/src/pl/plpython/plpython.c +++ b/src/pl/plpython/plpython.c @@ -29,7 +29,7 @@ * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.41.2.3 2006/02/20 20:10:45 neilc Exp $ + * $Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.41.2.4 2007/11/23 01:48:08 alvherre Exp $ * ********************************************************************* */ @@ -55,6 +55,7 @@ #include "commands/trigger.h" #include "executor/spi.h" #include "fmgr.h" +#include "lib/stringinfo.h" #include "nodes/makefuncs.h" #include "parser/parse_type.h" #include "tcop/tcopprot.h" @@ -208,7 +209,6 @@ static char *PLy_procedure_name(PLyProcedure *); /* some utility functions */ static void *PLy_malloc(size_t); -static void *PLy_realloc(void *, size_t); static void PLy_free(void *); /* sub handlers for functions and triggers @@ -2604,8 +2604,6 @@ PLy_procedure_name(PLyProcedure * proc) */ static char *PLy_traceback(int *); -static char *PLy_vprintf(const char *fmt, va_list ap); -static char *PLy_printf(const char *fmt,...); void PLy_exception_set(PyObject * exc, const char *fmt,...) @@ -2624,18 +2622,27 @@ void PLy_elog(int elevel, const char *fmt,...) { DECLARE_EXC(); - va_list ap; - char *xmsg, - *emsg; + char *xmsg; + StringInfoData emsg; int xlevel; enter(); 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); + } SAVE_EXC(); if (TRAP_EXC()) @@ -2647,19 +2654,19 @@ PLy_elog(int elevel, const char *fmt,...) * elog called siglongjmp. cleanup, restore and reraise */ PLy_restart_in_progress += 1; - PLy_free(emsg); + pfree(emsg.data); if (xmsg) - PLy_free(xmsg); + pfree(xmsg); RERAISE_EXC(); } ereport(elevel, - (errmsg("plpython: %s", emsg), + (errmsg("plpython: %s", emsg.data), (xmsg) ? errdetail("%s", xmsg) : 0)); - PLy_free(emsg); + pfree(emsg.data); if (xmsg) - PLy_free(xmsg); + pfree(xmsg); leave(); @@ -2675,8 +2682,8 @@ PLy_traceback(int *xlevel) PyObject *eob, *vob = NULL; char *vstr, - *estr, - *xstr = NULL; + *estr; + StringInfoData xstr; enter(); @@ -2710,7 +2717,8 @@ PLy_traceback(int *xlevel) * NULL here -- would an 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); @@ -2729,49 +2737,7 @@ PLy_traceback(int *xlevel) Py_DECREF(e); leave(); - return xstr; -} - -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; -} - -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 @@ -2793,18 +2759,6 @@ PLy_malloc(size_t bytes) return ptr; } -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 */ void