You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2026-05-22 10:15:16 +02:00
Add validation for WAL segment size in pg_control.
This serves as an additional sanity check to be sure the pg_control format is as expected. The field is useful for being near the end and containing a limited number of discrete values.
This commit is contained in:
@@ -180,6 +180,14 @@ pgWalSegmentSizeCheck(unsigned int pgVersion, unsigned int walSegmentSize)
|
|||||||
PG_WAL_SEGMENT_SIZE_DEFAULT);
|
PG_WAL_SEGMENT_SIZE_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that the WAL segment size is valid
|
||||||
|
if (!IsValidWalSegSize(walSegmentSize))
|
||||||
|
{
|
||||||
|
THROW_FMT(
|
||||||
|
FormatError, "wal segment size is %u but must be a power of two between %d and %d inclusive", walSegmentSize,
|
||||||
|
WalSegMinSize, WalSegMaxSize);
|
||||||
|
}
|
||||||
|
|
||||||
FUNCTION_TEST_RETURN_VOID();
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -244,4 +244,22 @@ Types from src/include/access/transam.h
|
|||||||
*/
|
*/
|
||||||
#define FirstNormalObjectId 16384
|
#define FirstNormalObjectId 16384
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Types from src/include/access/xlog_internal.h
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
|
||||||
|
// WalSegMinSize/WalSegMinSize macros
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
/* wal_segment_size can range from 1MB to 1GB */
|
||||||
|
#define WalSegMinSize 1024 * 1024
|
||||||
|
#define WalSegMaxSize 1024 * 1024 * 1024
|
||||||
|
|
||||||
|
// IsPowerOf2/IsValidWalSegSize macros
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
/* check that the given size is a valid wal_segment_size */
|
||||||
|
#define IsPowerOf2(x) (x > 0 && ((x) & ((x)-1)) == 0)
|
||||||
|
#define IsValidWalSegSize(size) \
|
||||||
|
(IsPowerOf2(size) && \
|
||||||
|
((size) >= WalSegMinSize && (size) <= WalSegMaxSize))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -193,7 +193,9 @@ hrnPgControlToBuffer(const unsigned int controlVersion, const unsigned int crc,
|
|||||||
|
|
||||||
// Set defaults if values are not passed
|
// Set defaults if values are not passed
|
||||||
pgControl.pageSize = pgControl.pageSize == 0 ? pgPageSize8 : pgControl.pageSize;
|
pgControl.pageSize = pgControl.pageSize == 0 ? pgPageSize8 : pgControl.pageSize;
|
||||||
pgControl.walSegmentSize = pgControl.walSegmentSize == 0 ? PG_WAL_SEGMENT_SIZE_DEFAULT : pgControl.walSegmentSize;
|
pgControl.walSegmentSize =
|
||||||
|
pgControl.walSegmentSize == UINT_MAX ?
|
||||||
|
0 : (pgControl.walSegmentSize == 0 ? PG_WAL_SEGMENT_SIZE_DEFAULT : pgControl.walSegmentSize);
|
||||||
pgControl.catalogVersion =
|
pgControl.catalogVersion =
|
||||||
pgControl.catalogVersion == 0 ? hrnPgInterfaceVersion(pgControl.version)->catalogVersion() : pgControl.catalogVersion;
|
pgControl.catalogVersion == 0 ? hrnPgInterfaceVersion(pgControl.version)->catalogVersion() : pgControl.catalogVersion;
|
||||||
pgControl.systemId = pgControl.systemId < 100 ? hrnPgSystemId(pgControl.version) + pgControl.systemId : pgControl.systemId;
|
pgControl.systemId = pgControl.systemId < 100 ? hrnPgSystemId(pgControl.version) + pgControl.systemId : pgControl.systemId;
|
||||||
|
|||||||
@@ -127,6 +127,31 @@ testRun(void)
|
|||||||
pgControlFromFile(storageTest, NULL), FormatError,
|
pgControlFromFile(storageTest, NULL), FormatError,
|
||||||
"wal segment size is 1048576 but must be 16777216 for PostgreSQL <= 10");
|
"wal segment size is 1048576 but must be 16777216 for PostgreSQL <= 10");
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
|
HRN_PG_CONTROL_PUT(storageTest, PG_VERSION_11, .walSegmentSize = UINT_MAX); // UINT_MAX forces size to 0
|
||||||
|
|
||||||
|
TEST_ERROR(
|
||||||
|
pgControlFromFile(storageTest, NULL), FormatError,
|
||||||
|
"wal segment size is 0 but must be a power of two between 1048576 and 1073741824 inclusive");
|
||||||
|
|
||||||
|
HRN_PG_CONTROL_PUT(storageTest, PG_VERSION_11, .walSegmentSize = 1);
|
||||||
|
|
||||||
|
TEST_ERROR(
|
||||||
|
pgControlFromFile(storageTest, NULL), FormatError,
|
||||||
|
"wal segment size is 1 but must be a power of two between 1048576 and 1073741824 inclusive");
|
||||||
|
|
||||||
|
HRN_PG_CONTROL_PUT(storageTest, PG_VERSION_11, .walSegmentSize = 47);
|
||||||
|
|
||||||
|
TEST_ERROR(
|
||||||
|
pgControlFromFile(storageTest, NULL), FormatError,
|
||||||
|
"wal segment size is 47 but must be a power of two between 1048576 and 1073741824 inclusive");
|
||||||
|
|
||||||
|
HRN_PG_CONTROL_PUT(storageTest, PG_VERSION_11, .walSegmentSize = (unsigned int)2 * 1024 * 1024 * 1024);
|
||||||
|
|
||||||
|
TEST_ERROR(
|
||||||
|
pgControlFromFile(storageTest, NULL), FormatError,
|
||||||
|
"wal segment size is 2147483648 but must be a power of two between 1048576 and 1073741824 inclusive");
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
HRN_PG_CONTROL_PUT(storageTest, PG_VERSION_95, .pageSize = 64 * 1024);
|
HRN_PG_CONTROL_PUT(storageTest, PG_VERSION_95, .pageSize = 64 * 1024);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user