From 93e69498b78d09261602aa4f4cf7c7c8fe0ee790 Mon Sep 17 00:00:00 2001 From: alterego655 <824662526@qq.com> Date: Wed, 19 Aug 2026 23:01:53 +0800 Subject: [PATCH v2] Fix overflow in WAIT FOR LSN timeout handling WAIT FOR accepted timeout values up to int64, but WaitForLSN converted milliseconds to microseconds without overflow checking. A sufficiently large value could therefore produce an invalid deadline and an immediate false timeout. Limit the timeout to the int range and use int consistently throughout the WaitForLSN interface, matching PostgreSQL's other timeout facilities. --- src/backend/access/transam/xlogwait.c | 2 +- src/backend/commands/wait.c | 6 +++--- src/include/access/xlogwait.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/backend/access/transam/xlogwait.c b/src/backend/access/transam/xlogwait.c index ea1d2afba27..d3606f40acd 100644 --- a/src/backend/access/transam/xlogwait.c +++ b/src/backend/access/transam/xlogwait.c @@ -439,7 +439,7 @@ WaitLSNTypeRequiresRecovery(WaitLSNType t) * or replica got promoted before the target LSN reached. */ WaitLSNResult -WaitForLSN(WaitLSNType lsnType, XLogRecPtr targetLSN, int64 timeout) +WaitForLSN(WaitLSNType lsnType, XLogRecPtr targetLSN, int timeout) { XLogRecPtr currentLSN; WaitLSNProcInfo *procInfo; diff --git a/src/backend/commands/wait.c b/src/backend/commands/wait.c index 40a6ffde16b..d401d400e97 100644 --- a/src/backend/commands/wait.c +++ b/src/backend/commands/wait.c @@ -35,7 +35,7 @@ ExecWaitStmt(ParseState *pstate, WaitStmt *stmt, bool isTopLevel, DestReceiver *dest) { XLogRecPtr lsn; - int64 timeout = 0; + int timeout = 0; WaitLSNResult waitLSNResult; WaitLSNType lsnType = WAIT_LSN_TYPE_STANDBY_REPLAY; /* default */ bool throw = true; @@ -116,7 +116,7 @@ ExecWaitStmt(ParseState *pstate, WaitStmt *stmt, bool isTopLevel, dval = rint(dval); /* Range check */ - if (unlikely(isnan(dval) || !FLOAT8_FITS_IN_INT64(dval))) + if (unlikely(isnan(dval) || !FLOAT8_FITS_IN_INT32(dval))) ereport(ERROR, errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), errmsg("timeout value is out of range")); @@ -126,7 +126,7 @@ ExecWaitStmt(ParseState *pstate, WaitStmt *stmt, bool isTopLevel, errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("timeout cannot be negative")); - timeout = (int64) dval; + timeout = (int) dval; } else if (strcmp(defel->defname, "no_throw") == 0) { diff --git a/src/include/access/xlogwait.h b/src/include/access/xlogwait.h index 07157f220ea..2bf0263e9e2 100644 --- a/src/include/access/xlogwait.h +++ b/src/include/access/xlogwait.h @@ -104,6 +104,6 @@ extern XLogRecPtr GetCurrentLSNForWaitType(WaitLSNType lsnType); extern void WaitLSNWakeup(WaitLSNType lsnType, XLogRecPtr currentLSN); extern void WaitLSNCleanup(void); extern WaitLSNResult WaitForLSN(WaitLSNType lsnType, XLogRecPtr targetLSN, - int64 timeout); + int timeout); #endif /* XLOG_WAIT_H */ -- 2.39.5 (Apple Git-154)