*** a/src/pl/plperl/Util.xs
--- b/src/pl/plperl/Util.xs
***************
*** 37,47 **** static void
  do_util_elog(int level, SV *msg)
  {
  	MemoryContext oldcontext = CurrentMemoryContext;
! 	char	   * volatile cmsg = NULL;
  
  	PG_TRY();
  	{
- 		cmsg = sv2cstr(msg);
  		elog(level, "%s", cmsg);
  		pfree(cmsg);
  	}
--- 37,46 ----
  do_util_elog(int level, SV *msg)
  {
  	MemoryContext oldcontext = CurrentMemoryContext;
! 	char	   * volatile cmsg = sv2cstr(msg);
  
  	PG_TRY();
  	{
  		elog(level, "%s", cmsg);
  		pfree(cmsg);
  	}
*** a/src/pl/plperl/plperl_helpers.h
--- b/src/pl/plperl/plperl_helpers.h
***************
*** 47,74 **** sv2cstr(SV *sv)
  {
  	char	   *val, *res;
  	STRLEN		len;
! 	SV         *nsv;
  
  	/*
  	 * get a utf8 encoded char * out of perl. *note* it may not be valid utf8!
  	 *
! 	 * SvPVutf8() croaks nastily on certain things, like typeglobs and
! 	 * readonly objects such as $^V. That's a perl bug - it's not supposed to
! 	 * happen. To avoid crashing the backend, we make a copy of the
! 	 * sv before passing it to SvPVutf8(). The copy is garbage collected 
! 	 * when we're done with it.
  	 */
! 	nsv = newSVsv(sv);
! 	val = SvPVutf8(nsv, len);
  
  	/*
  	 * we use perl's length in the event we had an embedded null byte to ensure
  	 * we error out properly
  	 */
! 	res =  utf_u2e(val, len);
  
  	/* safe now to garbage collect the new SV */
! 	SvREFCNT_dec(nsv);
  
  	return res;
  }
--- 47,79 ----
  {
  	char	   *val, *res;
  	STRLEN		len;
! 	svtype		type = SvTYPE(sv);
  
  	/*
  	 * get a utf8 encoded char * out of perl. *note* it may not be valid utf8!
  	 *
! 	 * SvPVutf8() croaks nastily on readonly refs, That's a perl bug - it's not
! 	 * supposed to happen. To avoid crashing the backend, we make a copy of the
! 	 * sv before passing it to SvPVutf8().
  	 */
! 	if (SvREADONLY(sv) &&
! 			(type != SVt_IV ||
! 			type != SVt_NV ||
! 			type != SVt_PV))
! 		sv = newSVsv(sv);
! 	else
! 		SvREFCNT_inc(sv);
! 
! 	val = SvPVutf8(sv, len);
  
  	/*
  	 * we use perl's length in the event we had an embedded null byte to ensure
  	 * we error out properly
  	 */
! 	res = utf_u2e(val, len);
  
  	/* safe now to garbage collect the new SV */
! 	SvREFCNT_dec(sv);
  
  	return res;
  }
