1
0
mirror of https://github.com/postgres/postgres.git synced 2025-04-27 22:56:53 +03:00

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
This commit is contained in:
Alexander Korotkov 2025-02-05 00:15:17 +02:00
parent 627d63419e
commit ff1975ddd0

View File

@ -97,6 +97,7 @@ main(int argc, char *argv[])
bool crc_ok; bool crc_ok;
char *DataDir = NULL; char *DataDir = NULL;
time_t time_tmp; time_t time_tmp;
struct tm *tm_tmp;
char pgctime_str[128]; char pgctime_str[128];
char ckpttime_str[128]; char ckpttime_str[128];
char mock_auth_nonce_str[MOCK_AUTH_NONCE_LEN * 2 + 1]; char mock_auth_nonce_str[MOCK_AUTH_NONCE_LEN * 2 + 1];
@ -196,20 +197,30 @@ main(int argc, char *argv[])
* about %c * about %c
*/ */
time_tmp = (time_t) ControlFile->time; time_tmp = (time_t) ControlFile->time;
strftime(pgctime_str, sizeof(pgctime_str), strftime_fmt, tm_tmp = localtime(&time_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; time_tmp = (time_t) ControlFile->checkPointCopy.time;
strftime(ckpttime_str, sizeof(ckpttime_str), strftime_fmt, tm_tmp = localtime(&time_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 * Calculate name of the WAL file containing the latest checkpoint's REDO
* start point. * start point.
* *
* A corrupted control file could report a WAL segment size of 0, and to * A corrupted control file could report a WAL segment size of 0 or
* guard against division by zero, we need to treat that specially. * negative value, and to guard against division by zero, we need to treat
* that specially.
*/ */
if (WalSegSz != 0) if (WalSegSz > 0)
{ {
XLogSegNo segno; XLogSegNo segno;