diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2017-07-19 16:16:57 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2017-07-19 16:16:57 -0400 |
commit | 3cb29c42f990522131535eea75c691fb23191685 (patch) | |
tree | 8535509f2ff02f2a82b3135c9d74eaa0ece233d9 /src/backend/access/transam/xlog.c | |
parent | 5752dcd45bd8b9a9115d4be12b9a391464884a39 (diff) | |
download | postgresql-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.c | 22 |
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) |