Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Check for relation length overrun soon enough.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 9 Sep 2021 15:45:48 +0000 (11:45 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
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/YTn1iTkUYBZfcODk@msg.credativ.de

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

index 4ceb2ce25bda8d63286a9bb87c8a20120eaf8bca..01c09fd532b370fd70f98a46ee2964a1794a0a57 100644 (file)
@@ -728,7 +728,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 1a28606b35cbac8df77f6c9d957a9c8660c18653..0c0e26b5229d8c02ac656d9126bdb77fca5b7b02 100644 (file)
@@ -424,7 +424,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,