diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 99cbcaa..864ec4e 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -220,6 +220,7 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
 		GistNSN		oldnsn = 0;
 		SplitedPageLayout rootpg;
 		bool		is_rootsplit;
+		int			npage;
 
 		is_rootsplit = (blkno == GIST_ROOT_BLKNO);
 
@@ -240,6 +241,15 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
 		itvec = gistjoinvector(itvec, &tlen, itup, ntup);
 		dist = gistSplit(rel, page, itvec, tlen, giststate);
 
+		/* Count the number of pages the original page was split into */
+		npage = 0;
+		for (ptr = dist; ptr; ptr = ptr->next)
+			npage++;
+
+		if (npage > GIST_MAX_SPLIT_PAGES)
+			elog(ERROR, "GiST page split into too many halves (%d, maximum %d)",
+				 npage, GIST_MAX_SPLIT_PAGES);
+
 		/*
 		 * Set up pages to work with. Allocate new buffers for all but the
 		 * leftmost page. The original page becomes the new leftmost page, and
@@ -402,7 +412,7 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
 		/* Write the WAL record */
 		if (RelationNeedsWAL(rel))
 			recptr = gistXLogSplit(rel->rd_node, blkno, is_leaf,
-								   dist, oldrlink, oldnsn, leftchildbuf,
+								   dist, npage, oldrlink, oldnsn, leftchildbuf,
 								   markfollowright);
 		else
 			recptr = gistGetFakeLSN(rel);
diff --git a/src/backend/access/gist/gistxlog.c b/src/backend/access/gist/gistxlog.c
index 17946bf..512c2f5 100644
--- a/src/backend/access/gist/gistxlog.c
+++ b/src/backend/access/gist/gistxlog.c
@@ -375,21 +375,23 @@ gist_xlog_cleanup(void)
  */
 XLogRecPtr
 gistXLogSplit(RelFileNode node, BlockNumber blkno, bool page_is_leaf,
-			  SplitedPageLayout *dist,
+			  SplitedPageLayout *dist, int npage,
 			  BlockNumber origrlink, GistNSN orignsn,
 			  Buffer leftchildbuf, bool markfollowright)
 {
-	XLogRecData *rdata;
+	XLogRecData rdata[GIST_MAX_SPLIT_PAGES * 2 + 2];
 	gistxlogPageSplit xlrec;
 	SplitedPageLayout *ptr;
-	int			npage = 0,
-				cur;
+	int			cur;
 	XLogRecPtr	recptr;
 
-	for (ptr = dist; ptr; ptr = ptr->next)
-		npage++;
-
-	rdata = (XLogRecData *) palloc(sizeof(XLogRecData) * (npage * 2 + 2));
+	/*
+	 * the caller should've checked this already, but doesn't hurt to check
+	 * again.
+	 */
+	if (npage > GIST_MAX_SPLIT_PAGES)
+		elog(ERROR, "GiST page split into too many halves (%d, maximum %d)",
+			 npage, GIST_MAX_SPLIT_PAGES);
 
 	xlrec.node = node;
 	xlrec.origblkno = blkno;
@@ -439,7 +441,6 @@ gistXLogSplit(RelFileNode node, BlockNumber blkno, bool page_is_leaf,
 
 	recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_PAGE_SPLIT, rdata);
 
-	pfree(rdata);
 	return recptr;
 }
 
@@ -462,14 +463,12 @@ gistXLogUpdate(RelFileNode node, Buffer buffer,
 			   IndexTuple *itup, int ituplen,
 			   Buffer leftchildbuf)
 {
-	XLogRecData *rdata;
+	XLogRecData rdata[MaxIndexTuplesPerPage + 3];
 	gistxlogPageUpdate xlrec;
 	int			cur,
 				i;
 	XLogRecPtr	recptr;
 
-	rdata = (XLogRecData *) palloc(sizeof(XLogRecData) * (3 + ituplen));
-
 	xlrec.node = node;
 	xlrec.blkno = BufferGetBlockNumber(buffer);
 	xlrec.ntodelete = ntodelete;
@@ -516,6 +515,5 @@ gistXLogUpdate(RelFileNode node, Buffer buffer,
 
 	recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_PAGE_UPDATE, rdata);
 
-	pfree(rdata);
 	return recptr;
 }
diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h
index cae6dbc..2d04af6 100644
--- a/src/include/access/gist_private.h
+++ b/src/include/access/gist_private.h
@@ -22,6 +22,22 @@
 #include "utils/rbtree.h"
 #include "utils/hsearch.h"
 
+/*
+ * Maximum number of "halves" a page can be split into in one operation.
+ * Typically a split produces 2 halves, but can be more if keys have very
+ * different lengths, or when inserting multiple keys in one operation (as
+ * when inserting downlinks to an internal node). There is no theoretical
+ * limit on this, but in practice if you get more than a handful page halves
+ * in one split, there'something wrong with the opclass implementation.
+ * GIST_MAX_SPLIT_PAGES is an arbitrary limit on that, used to size some
+ * local arrays used during split. Note that there is also a limit on the
+ * number of buffers that can be held locked at a time, MAX_SIMUL_LWLOCKS,
+ * so if you raise this higher than that limit, you'll just get a different
+ * error.
+ */
+#define GIST_MAX_SPLIT_PAGES		75
+
+
 /* Buffer lock modes */
 #define GIST_SHARE	BUFFER_LOCK_SHARE
 #define GIST_EXCLUSIVE	BUFFER_LOCK_EXCLUSIVE
@@ -447,7 +463,7 @@ extern XLogRecPtr gistXLogUpdate(RelFileNode node, Buffer buffer,
 
 extern XLogRecPtr gistXLogSplit(RelFileNode node,
 			  BlockNumber blkno, bool page_is_leaf,
-			  SplitedPageLayout *dist,
+			  SplitedPageLayout *dist, int npage,
 			  BlockNumber origrlink, GistNSN oldnsn,
 			  Buffer leftchild, bool markfollowright);
 
