Check for relation length overrun soon enough.
authorTom Lane <[email protected]>
Thu, 9 Sep 2021 15:45:48 +0000 (11:45 -0400)
committerTom Lane <[email protected]>
Thu, 9 Sep 2021 15:45:48 +0000 (11:45 -0400)
We don't allow relations to exceed 2^32-1 blocks, because block
numbers are 32 bits and the last possible block number is reserved
to mean InvalidBlockNumber.  There is a check for this in mdextend,
but that's really way too late, because the smgr API requires us to
create a buffer for the block-to-be-added, and we do not want to
have any buffer with blocknum InvalidBlockNumber.  (Such a case
can trigger assertions in bufmgr.c, plus I think it might confuse
ReadBuffer's logic for data-past-EOF later on.)  So put the check
into ReadBuffer.

Per report from Christoph Berg.  It's been like this forever,
so back-patch to all supported branches.

Discussion: https://postgr.es/m/[email protected]

src/backend/storage/buffer/bufmgr.c
src/backend/storage/smgr/md.c

index bc1753ae916068cdf9e9d690a0f57b22b6c0b63d..e88e4e918b0951b263852a0aaf2e7d0584b15e65 100644 (file)
@@ -824,7 +824,16 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 
        /* Substitute proper block number if caller asked for P_NEW */
        if (isExtend)
+       {
                blockNum = smgrnblocks(smgr, forkNum);
+               /* Fail if relation is already at maximum possible length */
+               if (blockNum == P_NEW)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+                                        errmsg("cannot extend relation %s beyond %u blocks",
+                                                       relpath(smgr->smgr_rnode, forkNum),
+                                                       P_NEW)));
+       }
 
        if (isLocalBuf)
        {
index 1e12cfad8e855ab4e3dd56b0947a9dacf2c6ba67..b4bca7eed6fe437199b12a31986d35268875c58a 100644 (file)
@@ -426,7 +426,8 @@ mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
        /*
         * If a relation manages to grow to 2^32-1 blocks, refuse to extend it any
         * more --- we mustn't create a block whose number actually is
-        * InvalidBlockNumber.
+        * InvalidBlockNumber.  (Note that this failure should be unreachable
+        * because of upstream checks in bufmgr.c.)
         */
        if (blocknum == InvalidBlockNumber)
                ereport(ERROR,