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

Reply via email to