aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/transam/xlog.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2017-07-19 16:16:57 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2017-07-19 16:16:57 -0400
commit3cb29c42f990522131535eea75c691fb23191685 (patch)
tree8535509f2ff02f2a82b3135c9d74eaa0ece233d9 /src/backend/access/transam/xlog.c
parent5752dcd45bd8b9a9115d4be12b9a391464884a39 (diff)
downloadpostgresql-3cb29c42f990522131535eea75c691fb23191685.tar.gz
postgresql-3cb29c42f990522131535eea75c691fb23191685.zip
Add static assertions about pg_control fitting into one disk sector.
When pg_control was first designed, sizeof(ControlFileData) was small enough that a comment seemed like plenty to document the assumption that it'd fit into one disk sector. Now it's nearly 300 bytes, raising the possibility that somebody would carelessly add enough stuff to create a problem. Let's add a StaticAssertStmt() to ensure that the situation doesn't pass unnoticed if it ever occurs. While at it, rename PG_CONTROL_SIZE to PG_CONTROL_FILE_SIZE to make it clearer what that symbol means, and convert the existing runtime comparisons of sizeof(ControlFileData) vs. PG_CONTROL_FILE_SIZE to be static asserts --- we didn't have that technology when this code was first written. Discussion: https://postgr.es/m/9192.1500490591@sss.pgh.pa.us
Diffstat (limited to 'src/backend/access/transam/xlog.c')
-rw-r--r--src/backend/access/transam/xlog.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 5b6cec8deed..3654543919f 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -4376,7 +4376,16 @@ static void
WriteControlFile(void)
{
int fd;
- char buffer[PG_CONTROL_SIZE]; /* need not be aligned */
+ char buffer[PG_CONTROL_FILE_SIZE]; /* need not be aligned */
+
+ /*
+ * Ensure that the size of the pg_control data structure is sane. See the
+ * comments for these symbols in pg_control.h.
+ */
+ StaticAssertStmt(sizeof(ControlFileData) <= PG_CONTROL_MAX_SAFE_SIZE,
+ "pg_control is too large for atomic disk writes");
+ StaticAssertStmt(sizeof(ControlFileData) <= PG_CONTROL_FILE_SIZE,
+ "sizeof(ControlFileData) exceeds PG_CONTROL_FILE_SIZE");
/*
* Initialize version and compatibility-check fields
@@ -4409,16 +4418,13 @@ WriteControlFile(void)
FIN_CRC32C(ControlFile->crc);
/*
- * We write out PG_CONTROL_SIZE bytes into pg_control, zero-padding the
- * excess over sizeof(ControlFileData). This reduces the odds of
+ * We write out PG_CONTROL_FILE_SIZE bytes into pg_control, zero-padding
+ * the excess over sizeof(ControlFileData). This reduces the odds of
* premature-EOF errors when reading pg_control. We'll still fail when we
* check the contents of the file, but hopefully with a more specific
* error than "couldn't read pg_control".
*/
- if (sizeof(ControlFileData) > PG_CONTROL_SIZE)
- elog(PANIC, "sizeof(ControlFileData) is larger than PG_CONTROL_SIZE; fix either one");
-
- memset(buffer, 0, PG_CONTROL_SIZE);
+ memset(buffer, 0, PG_CONTROL_FILE_SIZE);
memcpy(buffer, ControlFile, sizeof(ControlFileData));
fd = BasicOpenFile(XLOG_CONTROL_FILE,
@@ -4432,7 +4438,7 @@ WriteControlFile(void)
errno = 0;
pgstat_report_wait_start(WAIT_EVENT_CONTROL_FILE_WRITE);
- if (write(fd, buffer, PG_CONTROL_SIZE) != PG_CONTROL_SIZE)
+ if (write(fd, buffer, PG_CONTROL_FILE_SIZE) != PG_CONTROL_FILE_SIZE)
{
/* if write didn't set errno, assume problem is no disk space */
if (errno == 0)