Tom Lane escribió:
> "Marko Kreen" <[EMAIL PROTECTED]> writes:
> > Following function crashes plpython on x86-64 / gcc 4.1.2 / debian 4.0:
> > CREATE FUNCTION crashme(str_len integer)
> > RETURNS text AS $$
> > raise Exception("X" * str_len)
> > $$ LANGUAGE plpythonu;
>
> > SELECT crashme(1000);
>
> > Problem turns out to be va_list handling in PLy_vprintf() which
> > uses same va_list repeatedly. Fix is to va_copy to temp variable.
>
> This patch isn't acceptable because va_copy() isn't portable.
>
> I'm kinda wondering why PLy_printf and the functions after it even
> exist. They look like rather poorly done reimplementations of
> functionality that exists elsewhere in the backend (eg, stringinfo.c).
> In particular, why malloc and not palloc?
See attached patch.
I didn't bother to change the PLy_malloc and friends because I think
that would be too much change for 8.3. PLy_realloc is gone though
because there are no callers left after this patch.
--
Alvaro Herrera http://www.flickr.com/photos/alvherre/
"Ninguna manada de bestias tiene una voz tan horrible como la humana" (Orual)
Index: src/pl/plpython/plpython.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/pl/plpython/plpython.c,v
retrieving revision 1.104
diff -c -p -r1.104 plpython.c
*** src/pl/plpython/plpython.c 15 Nov 2007 21:14:46 -0000 1.104
--- src/pl/plpython/plpython.c 22 Nov 2007 18:11:02 -0000
*************** static char *PLy_procedure_name(PLyProce
*** 210,220 ****
/* 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 *);
--- 210,217 ----
*************** PLy_exception_set(PyObject * exc, const
*** 2900,2934 ****
static void
PLy_elog(int elevel, const char *fmt,...)
{
! va_list ap;
! char *xmsg,
! *emsg;
int xlevel;
xmsg = PLy_traceback(&xlevel);
! va_start(ap, fmt);
! emsg = PLy_vprintf(fmt, ap);
! va_end(ap);
PG_TRY();
{
ereport(elevel,
! (errmsg("plpython: %s", emsg),
(xmsg) ? errdetail("%s", xmsg) : 0));
}
PG_CATCH();
{
! PLy_free(emsg);
if (xmsg)
! PLy_free(xmsg);
PG_RE_THROW();
}
PG_END_TRY();
! PLy_free(emsg);
if (xmsg)
! PLy_free(xmsg);
}
static char *
--- 2897,2940 ----
static void
PLy_elog(int elevel, const char *fmt,...)
{
! char *xmsg;
int xlevel;
+ StringInfoData emsg;
xmsg = PLy_traceback(&xlevel);
! 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.data),
(xmsg) ? errdetail("%s", xmsg) : 0));
}
PG_CATCH();
{
! pfree(emsg.data);
if (xmsg)
! pfree(xmsg);
PG_RE_THROW();
}
PG_END_TRY();
! pfree(emsg.data);
if (xmsg)
! pfree(xmsg);
}
static char *
*************** PLy_traceback(int *xlevel)
*** 2940,2947 ****
PyObject *eob,
*vob = NULL;
char *vstr,
! *estr,
! *xstr = NULL;
/*
* get the current exception
--- 2946,2953 ----
PyObject *eob,
*vob = NULL;
char *vstr,
! *estr;
! StringInfoData xstr;
/*
* get the current exception
*************** PLy_traceback(int *xlevel)
*** 2973,2979 ****
* Assert() be more appropriate?
*/
estr = eob ? PyString_AsString(eob) : "Unknown Exception";
! xstr = PLy_printf("%s: %s", estr, vstr);
Py_DECREF(eob);
Py_XDECREF(vob);
--- 2979,2986 ----
* Assert() be more appropriate?
*/
estr = eob ? PyString_AsString(eob) : "Unknown Exception";
! initStringInfo(&xstr);
! appendStringInfo(&xstr, "%s: %s", estr, vstr);
Py_DECREF(eob);
Py_XDECREF(vob);
*************** PLy_traceback(int *xlevel)
*** 2990,3038 ****
*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;
}
/* python module code */
--- 2997,3003 ----
*xlevel = ERROR;
Py_DECREF(e);
! return xstr.data;
}
/* python module code */
*************** PLy_malloc(size_t bytes)
*** 3050,3067 ****
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)
{
--- 3015,3020 ----
---------------------------(end of broadcast)---------------------------
TIP 2: Don't 'kill -9' the postmaster