aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlexander Korotkov <akorotkov@postgresql.org>2025-02-05 00:15:17 +0200
committerAlexander Korotkov <akorotkov@postgresql.org>2025-02-05 00:45:37 +0200
commitd54d5668b4d7ef44e2c8475ed3944686293e9829 (patch)
tree08dcef5b6dace593ae6955b4d615c5587748a0b1 /src
parente8d8174caf75c5724847b43b886a7feb1628c4d4 (diff)
downloadpostgresql-d54d5668b4d7ef44e2c8475ed3944686293e9829.tar.gz
postgresql-d54d5668b4d7ef44e2c8475ed3944686293e9829.zip
pg_controldata: Fix possible errors on corrupted pg_control
Protect against malformed timestamps. Also protect against negative WalSegSz as it triggers division by zero: ((0x100000000UL) / (WalSegSz)) can turn into zero in XLogFileName(xlogfilename, ControlFile->checkPointCopy.ThisTimeLineID, segno, WalSegSz); because if WalSegSz is -1 then by arithmetic rules in C we get 0x100000000UL / 0xFFFFFFFFFFFFFFFFUL == 0. Author: Ilyasov Ian <ianilyasov@outlook.com> Author: Anton Voloshin <a.voloshin@postgrespro.ru> Backpatch-through: 13
Diffstat (limited to 'src')
-rw-r--r--src/bin/pg_controldata/pg_controldata.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/src/bin/pg_controldata/pg_controldata.c b/src/bin/pg_controldata/pg_controldata.c
index c390ec51ce9..a54ceb4eba5 100644
--- a/src/bin/pg_controldata/pg_controldata.c
+++ b/src/bin/pg_controldata/pg_controldata.c
@@ -97,6 +97,7 @@ main(int argc, char *argv[])
bool crc_ok;
char *DataDir = NULL;
time_t time_tmp;
+ struct tm *tm_tmp;
char pgctime_str[128];
char ckpttime_str[128];
char mock_auth_nonce_str[MOCK_AUTH_NONCE_LEN * 2 + 1];
@@ -197,20 +198,30 @@ main(int argc, char *argv[])
* about %c
*/
time_tmp = (time_t) ControlFile->time;
- strftime(pgctime_str, sizeof(pgctime_str), strftime_fmt,
- localtime(&time_tmp));
+ tm_tmp = localtime(&time_tmp);
+
+ if (tm_tmp != NULL)
+ strftime(pgctime_str, sizeof(pgctime_str), strftime_fmt, tm_tmp);
+ else
+ snprintf(pgctime_str, sizeof(pgctime_str), _("???"));
+
time_tmp = (time_t) ControlFile->checkPointCopy.time;
- strftime(ckpttime_str, sizeof(ckpttime_str), strftime_fmt,
- localtime(&time_tmp));
+ tm_tmp = localtime(&time_tmp);
+
+ if (tm_tmp != NULL)
+ strftime(ckpttime_str, sizeof(ckpttime_str), strftime_fmt, tm_tmp);
+ else
+ snprintf(ckpttime_str, sizeof(ckpttime_str), _("???"));
/*
* Calculate name of the WAL file containing the latest checkpoint's REDO
* start point.
*
- * A corrupted control file could report a WAL segment size of 0, and to
- * guard against division by zero, we need to treat that specially.
+ * A corrupted control file could report a WAL segment size of 0 or
+ * negative value, and to guard against division by zero, we need to treat
+ * that specially.
*/
- if (WalSegSz != 0)
+ if (WalSegSz > 0)
{
XLogSegNo segno;