Document issue with heapam line pointer truncation.
authorPeter Geoghegan <pg@bowt.ie>
Thu, 23 Sep 2021 02:21:36 +0000 (19:21 -0700)
committerPeter Geoghegan <pg@bowt.ie>
Thu, 23 Sep 2021 02:21:36 +0000 (19:21 -0700)
Checking that an offset number isn't past the end of a heap page's line
pointer array was just a defensive sanity check for HOT-chain traversal
code before commit 3c3b8a4b.  It's etrictly necessary now, though.  Add
comments that reference the issue to code in heapam that needs to get it
right.

Per suggestion from Alexander Lakhin.

Discussion: https://postgr.es/m/f76a292c-9170-1aef-91a0-59d9443b99a3@gmail.com

src/backend/access/heap/heapam.c
src/backend/access/heap/pruneheap.c

index 972fdbcb92f1088905f03f6fc554f25ace212ef5..2a264c6ac1f3282f7b22754bd919ad7180c2c36b 100644 (file)
@@ -7483,8 +7483,15 @@ heap_index_delete_tuples(Relation rel, TM_IndexDeleteOp *delstate)
                        ItemId          lp;
                        HeapTupleHeader htup;
 
-                       /* Some sanity checks */
-                       if (offnum < FirstOffsetNumber || offnum > maxoff)
+                       /* Sanity check (pure paranoia) */
+                       if (offnum < FirstOffsetNumber)
+                               break;
+
+                       /*
+                        * An offset past the end of page's line pointer array is possible
+                        * when the array was truncated
+                        */
+                       if (offnum > maxoff)
                                break;
 
                        lp = PageGetItemId(page, offnum);
index 15ca1b304a085d850c837ad15dec56f7b07c5d24..db6912e9fa59b87eb4b1a6c1213e9c2368c195b0 100644 (file)
@@ -581,8 +581,15 @@ heap_prune_chain(Buffer buffer, OffsetNumber rootoffnum, PruneState *prstate)
                bool            tupdead,
                                        recent_dead;
 
-               /* Some sanity checks */
-               if (offnum < FirstOffsetNumber || offnum > maxoff)
+               /* Sanity check (pure paranoia) */
+               if (offnum < FirstOffsetNumber)
+                       break;
+
+               /*
+                * An offset past the end of page's line pointer array is possible
+                * when the array was truncated (original item must have been unused)
+                */
+               if (offnum > maxoff)
                        break;
 
                /* If item is already processed, stop --- it must not be same chain */
@@ -962,8 +969,15 @@ heap_get_root_tuples(Page page, OffsetNumber *root_offsets)
                 */
                for (;;)
                {
-                       /* Sanity check */
-                       if (nextoffnum < FirstOffsetNumber || nextoffnum > maxoff)
+                       /* Sanity check (pure paranoia) */
+                       if (offnum < FirstOffsetNumber)
+                               break;
+
+                       /*
+                        * An offset past the end of page's line pointer array is possible
+                        * when the array was truncated
+                        */
+                       if (offnum > maxoff)
                                break;
 
                        lp = PageGetItemId(page, nextoffnum);