diff --git a/src/backend/access/gin/ginpostinglist.c b/src/backend/access/gin/ginpostinglist.c
index 48ccfafdd224aa9e1aac4746d1c25cc3b9bbe13f..44aef77edb72d82bf7bfd9c416f48bfa768adba3 100644
--- a/src/backend/access/gin/ginpostinglist.c
+++ b/src/backend/access/gin/ginpostinglist.c
@@ -23,25 +23,32 @@
 /*
  * For encoding purposes, item pointers are represented as 64-bit unsigned
  * integers. The lowest 11 bits represent the offset number, and the next
- * lowest 32 bits are the block number. That leaves 17 bits unused, i.e.
+ * lowest 32 bits are the block number. That leaves 21 bits unused, i.e.
  * only 43 low bits are used.
  *
+ * 11 bits is enough for the offset number, because MaxHeapTuplesPerPage <
+ * 2^11 on all supported block sizes. We are frugal with the bits, because
+ * smaller integers use fewer bytes in the varbyte encoding, saving disk
+ * space. (If we get a new table AM in the future that wants to use the full
+ * range of possible offset numbers, we'll need to change this.)
+ *
  * These 43-bit integers are encoded using varbyte encoding. In each byte,
  * the 7 low bits contain data, while the highest bit is a continuation bit.
  * When the continuation bit is set, the next byte is part of the same
- * integer, otherwise this is the last byte of this integer.  43 bits fit
- * conveniently in at most 6 bytes when varbyte encoded (the 6th byte does
- * not need a continuation bit, because we know the max size to be 43 bits):
+ * integer, otherwise this is the last byte of this integer. 43 bits need
+ * at most 7 bytes in this encoding:
  *
  * 0XXXXXXX
  * 1XXXXXXX 0XXXXYYY
  * 1XXXXXXX 1XXXXYYY 0YYYYYYY
  * 1XXXXXXX 1XXXXYYY 1YYYYYYY 0YYYYYYY
  * 1XXXXXXX 1XXXXYYY 1YYYYYYY 1YYYYYYY 0YYYYYYY
- * 1XXXXXXX 1XXXXYYY 1YYYYYYY 1YYYYYYY 1YYYYYYY YYYYYYYY
+ * 1XXXXXXX 1XXXXYYY 1YYYYYYY 1YYYYYYY 1YYYYYYY 0YYYYYYY
+ * 1XXXXXXX 1XXXXYYY 1YYYYYYY 1YYYYYYY 1YYYYYYY 1YYYYYYY 0uuuuuuY
  *
  * X = bits used for offset number
  * Y = bits used for block number
+ * u = unused bit
  *
  * The bytes are in stored in little-endian order.
  *
@@ -73,6 +80,9 @@
  */
 #define MaxHeapTuplesPerPageBits		11
 
+/* Max. number of bytes needed to encode the largest supported integer. */
+#define MaxBytesPerInteger				7
+
 static inline uint64
 itemptr_to_uint64(const ItemPointer iptr)
 {
@@ -126,33 +136,40 @@ decode_varbyte(unsigned char **ptr)
 	unsigned char *p = *ptr;
 	uint64		c;
 
+	/* 1st byte */
 	c = *(p++);
 	val = c & 0x7F;
 	if (c & 0x80)
 	{
+		/* 2nd byte */
 		c = *(p++);
 		val |= (c & 0x7F) << 7;
 		if (c & 0x80)
 		{
+			/* 3rd byte */
 			c = *(p++);
 			val |= (c & 0x7F) << 14;
 			if (c & 0x80)
 			{
+				/* 4th byte */
 				c = *(p++);
 				val |= (c & 0x7F) << 21;
 				if (c & 0x80)
 				{
+					/* 5th byte */
 					c = *(p++);
 					val |= (c & 0x7F) << 28;
 					if (c & 0x80)
 					{
+						/* 6th byte */
 						c = *(p++);
 						val |= (c & 0x7F) << 35;
 						if (c & 0x80)
 						{
-							/* last byte, no continuation bit */
+							/* 7th byte, should not have continuation bit */
 							c = *(p++);
 							val |= c << 42;
+							Assert((c & 0x80) == 0);
 						}
 					}
 				}
@@ -208,15 +225,15 @@ ginCompressPostingList(const ItemPointer ipd, int nipd, int maxsize,
 
 		Assert(val > prev);
 
-		if (endptr - ptr >= 6)
+		if (endptr - ptr >= MaxBytesPerInteger)
 			encode_varbyte(delta, &ptr);
 		else
 		{
 			/*
-			 * There are less than 6 bytes left. Have to check if the next
+			 * There are less than 7 bytes left. Have to check if the next
 			 * item fits in that space before writing it out.
 			 */
-			unsigned char buf[6];
+			unsigned char buf[MaxBytesPerInteger];
 			unsigned char *p = buf;
 
 			encode_varbyte(delta, &p);