From 398cf255ad50db86ca665b75582317d4e795242a Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Fri, 24 Jan 2014 10:42:38 +0200 Subject: [PATCH] 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. --- src/backend/access/gin/gindatapage.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/backend/access/gin/gindatapage.c b/src/backend/access/gin/gindatapage.c index 8504f4c7af..ebdacd40c5 100644 --- a/src/backend/access/gin/gindatapage.c +++ b/src/backend/access/gin/gindatapage.c @@ -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; } -- 2.40.0