Fix buggy usage of vsnprintf in PL/Python by removing it altogether, instead
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Fri, 23 Nov 2007 01:48:08 +0000 (01:48 +0000)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Fri, 23 Nov 2007 01:48:08 +0000 (01:48 +0000)
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

index e811776599e806ff942d9596ff25d1a13dce6ce1..f765a685caee8f6328edd4b2ca8a870211abfcac 100644 (file)
@@ -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