In GIN recompression code, use mmemove rather than memcpy, for vacuum.

When vacuuming a data leaf page, any compressed posting lists that are not
modified, are copied back to the buffer from a later location in the same
buffer rather than from  a palloc'd copy. IOW, they are just moved
downwards in the same buffer. Because the source and destination addresses
can overlap, we must use memmove rather than memcpy.

Report and fix by Alexander Korotkov.
This commit is contained in:
Heikki Linnakangas 2014-01-24 10:42:38 +02:00
parent fbe19ee3b8
commit 398cf255ad

View File

@ -753,6 +753,13 @@ ginVacuumPostingTreeLeaf(Relation indexrel, Buffer buffer, GinVacuumState *gvs)
* *prdata is filled with WAL information about this operation. The caller
* is responsible for inserting to the WAL, along with any other information
* about the operation that triggered this recompression.
*
* NOTE: The segment pointers can point directly to the same buffer, with
* the limitation that any earlier segment must not overlap with an original,
* later segment. In other words, some segments may point the original buffer
* as long as you don't make any segments larger. Currently, leafRepackItems
* satisies this rule because it rewrites all segments after the first
* modified one, and vacuum can only make segments shorter.
*/
static void
dataPlaceToPageLeafRecompress(Buffer buf, disassembledLeaf *leaf,
@ -798,7 +805,13 @@ dataPlaceToPageLeafRecompress(Buffer buf, disassembledLeaf *leaf,
if (!modified)
unmodifiedsize += segsize;
else
memcpy(ptr, seginfo->seg, segsize);
{
/*
* Use memmove rather than memcpy, in case the segment points
* to the same buffer
*/
memmove(ptr, seginfo->seg, segsize);
}
ptr += segsize;
newsize += segsize;
}