bugfix: page, received from shared buffer, should be validated

This commit is contained in:
Grigory Smolkin
2020-04-22 18:35:19 +03:00
parent bebdef6c16
commit 058a3bd401
+36 -24
View File
@@ -418,43 +418,55 @@ prepare_page(ConnectionArgs *conn_arg,
&& (ptrack_version_num >= 15 && ptrack_version_num < 20)) && (ptrack_version_num >= 15 && ptrack_version_num < 20))
|| !page_is_valid) || !page_is_valid)
{ {
int rc = 0;
size_t page_size = 0; size_t page_size = 0;
Page ptrack_page = NULL; Page ptrack_page = NULL;
ptrack_page = (Page) pg_ptrack_get_block(conn_arg, file->dbOid, file->tblspcOid, page = (Page) pg_ptrack_get_block(conn_arg, file->dbOid, file->tblspcOid,
file->relOid, absolute_blknum, &page_size, file->relOid, absolute_blknum, &page_size,
ptrack_version_num, ptrack_schema); ptrack_version_num, ptrack_schema);
if (ptrack_page == NULL) if (ptrack_page == NULL)
{
/* This block was truncated.*/ /* This block was truncated.*/
return PageIsTruncated; return PageIsTruncated;
}
else if (page_size != BLCKSZ) if (page_size != BLCKSZ)
{
free(ptrack_page);
elog(ERROR, "File: \"%s\", block %u, expected block size %d, but read %zu", elog(ERROR, "File: \"%s\", block %u, expected block size %d, but read %zu",
from_fullpath, absolute_blknum, BLCKSZ, page_size); from_fullpath, absolute_blknum, BLCKSZ, page_size);
}
else /*
* We need to copy the page that was successfully
* retrieved from ptrack into our output "page" parameter.
*/
memcpy(page, ptrack_page, BLCKSZ);
pg_free(ptrack_page);
/* UPD: It apprears that is possible to get zeroed page or page with invalid header
* from shared buffer.
* Note, that getting page with wrong checksumm from shared buffer is
* acceptable.
*/
rc = validate_one_page(page, absolute_blknum,
InvalidXLogRecPtr, &page_lsn,
checksum_version);
/* It is ok to get zeroed page */
if (rc == PAGE_IS_ZEROED)
return PageIsOk;
/* Getting page with invalid header from shared buffers is unacceptable */
if (PAGE_HEADER_IS_INVALID)
{ {
/* char *errormsg = NULL;
* We need to copy the page that was successfully get_header_errormsg(page, &errormsg);
* retrieved from ptrack into our output "page" parameter. elog(ERROR, "Corruption detected in file \"%s\", block %u: %s",
* We must set checksum here, because it is outdated from_fullpath, blknum, errormsg);
* in the block recieved from shared buffers.
*/
memcpy(page, ptrack_page, BLCKSZ);
free(ptrack_page);
if (checksum_version)
((PageHeader) page)->pd_checksum = pg_checksum_page(page, absolute_blknum);
} }
/* get lsn from page, provided by pg_ptrack_get_block() */ /* We must set checksum here, because it is outdated
if (backup_mode == BACKUP_MODE_DIFF_DELTA && * in the block recieved from shared buffers.
file->exists_in_prev && */
!parse_page(page, &page_lsn)) if (checksum_version)
elog(ERROR, "Cannot parse page after pg_ptrack_get_block. " ((PageHeader) page)->pd_checksum = pg_checksum_page(page, absolute_blknum);
"Possible risk of a memory corruption");
} }
/* /*