Another error reported by valgrind on the postmaster (& children) is
the following:

==30568== Source and destination overlap in memcpy(0xBFFFEA30, 0xBFFFEA30, 24)
==30568==    at 0x40024224: memcpy (mac_replace_strmem.c:93)
==30568==    by 0x82081F3: set_var_from_var (numeric.c:2732)
==30568==    by 0x820BDF7: power_var_int (numeric.c:4572)
==30568==    by 0x820A74E: exp_var (numeric.c:4180)
==30568==    by 0x820BBF4: power_var (numeric.c:4514)
==30568==    by 0x8205AA0: numeric_power (numeric.c:1580)
==30568==    by 0x8141814: ExecMakeFunctionResult (execQual.c:907)
==30568==    by 0x8141FD5: ExecEvalFunc (execQual.c:1214)
==30568==    by 0x8143E61: ExecEvalExpr (execQual.c:2253)
==30568==    by 0x8141323: ExecEvalFuncArgs (execQual.c:678)
==30568==    by 0x81414A0: ExecMakeFunctionResult (execQual.c:736)
==30568==    by 0x8141FD5: ExecEvalFunc (execQual.c:1214)

[ triggered by one of the queries in the numeric regression test ]

I don't know of a memcpy() implementation that would actually bail out
if called with two equal pointers, but perhaps there is one in
existence somewhere. The attached patch (not yet applied) avoids this
case by returning early from set_var_from_var() if asked to assign a
numeric to itself. That also means we can skip a few memcpy()s and a
palloc(). The other way to fix this would be to just use memmove()
instead of memcpy() here: anyone have a preference?

Unless anyone objects, I'll apply this patch tonight.

-Neil
Index: src/backend/utils/adt/numeric.c
===================================================================
RCS file: /var/lib/cvs/pgsql-server/src/backend/utils/adt/numeric.c,v
retrieving revision 1.70
diff -c -r1.70 numeric.c
*** src/backend/utils/adt/numeric.c	2 Dec 2003 00:26:59 -0000	1.70
--- src/backend/utils/adt/numeric.c	2 Feb 2004 18:09:23 -0000
***************
*** 2723,2728 ****
--- 2723,2736 ----
  {
  	NumericDigit *newbuf;
  
+ 	/*
+ 	 * If asked to assign a variable to itself, return immediately:
+ 	 * it's a no-op, and we don't want to memcpy() an overlapping
+ 	 * memory range.
+ 	 */
+ 	if (value == dest)
+ 		return;
+ 
  	newbuf = digitbuf_alloc(value->ndigits + 1);
  	newbuf[0] = 0;				/* spare digit for rounding */
  	memcpy(newbuf + 1, value->digits, value->ndigits * sizeof(NumericDigit));
---------------------------(end of broadcast)---------------------------
TIP 4: Don't 'kill -9' the postmaster

Reply via email to