v2-0001-libpq-oauth-Avoid-overflow-for-very-large-interva.patch
application/octet-stream
Filename: v2-0001-libpq-oauth-Avoid-overflow-for-very-large-interva.patch
Type: application/octet-stream
Part: 0
Message:
Re: oauth integer overflow
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v2-0001
Subject: libpq-oauth: Avoid overflow for very large intervals
| File | + | − |
|---|---|---|
| src/interfaces/libpq-oauth/oauth-curl.c | 25 | 10 |
From d6d3a851e73fede3b3d601f735e099d3206c5cff Mon Sep 17 00:00:00 2001
From: Jacob Champion <jchampion@postgresql.org>
Date: Fri, 29 May 2026 16:21:46 -0700
Subject: [PATCH v2] libpq-oauth: Avoid overflow for very large intervals
The slow_down interval parsing code checks explicitly for overflow, but
since it does that after the signed overflow has already occurred, we
end up inviting undefined behavior from the compiler anyway.
Use checked arithmetic instead. set_timer() takes a long int in order to
interface nicely with libcurl, so use an int32 as the interval counter
and clamp to LONG_MAX during conversion to milliseconds.
Backpatch to 18, where libpq-oauth was introduced.
Reported-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Discussion: https://postgr.es/m/qtclihmrkq67ach3xjxyi4qcksstin5qxwsnkqefkmotxwh4g6%40ae2bj6jvcmry
Backpatch-through: 18
---
src/interfaces/libpq-oauth/oauth-curl.c | 35 ++++++++++++++++++-------
1 file changed, 25 insertions(+), 10 deletions(-)
diff --git a/src/interfaces/libpq-oauth/oauth-curl.c b/src/interfaces/libpq-oauth/oauth-curl.c
index 7ba75fc6d04..260137291cb 100644
--- a/src/interfaces/libpq-oauth/oauth-curl.c
+++ b/src/interfaces/libpq-oauth/oauth-curl.c
@@ -28,6 +28,7 @@
#error libpq-oauth is not supported on this platform
#endif
+#include "common/int.h"
#include "common/jsonapi.h"
#include "mb/pg_wchar.h"
#include "oauth-curl.h"
@@ -136,7 +137,7 @@ struct device_authz
/* Fields below are parsed from the corresponding string above. */
int expires_in;
- int interval;
+ int32 interval;
};
static void
@@ -1020,7 +1021,7 @@ parse_json_number(const char *s)
* expensive network polling loop.) Tests may remove the lower bound with
* PGOAUTHDEBUG, for improved performance.
*/
-static int
+static int32
parse_interval(struct async_ctx *actx, const char *interval_str)
{
double parsed;
@@ -1031,8 +1032,8 @@ parse_interval(struct async_ctx *actx, const char *interval_str)
if (parsed < 1)
return (actx->debug_flags & OAUTHDEBUG_UNSAFE_DOS_ENDPOINT) ? 0 : 1;
- else if (parsed >= INT_MAX)
- return INT_MAX;
+ else if (parsed >= INT32_MAX)
+ return INT32_MAX;
return parsed;
}
@@ -2620,10 +2621,7 @@ handle_token_response(struct async_ctx *actx, char **token)
*/
if (strcmp(err->error, "slow_down") == 0)
{
- int prev_interval = actx->authz.interval;
-
- actx->authz.interval += 5;
- if (actx->authz.interval < prev_interval)
+ if (pg_add_s32_overflow(actx->authz.interval, 5, &actx->authz.interval))
{
actx_error(actx, "slow_down interval overflow");
goto token_cleanup;
@@ -2949,8 +2947,25 @@ pg_fe_run_oauth_flow_impl(PGconn *conn, PGoauthBearerRequestV2 *request,
* Wait for the required interval before issuing the next
* request.
*/
- if (!set_timer(actx, actx->authz.interval * 1000))
- goto error_return;
+ {
+ /*
+ * Avoid overflow of long int. (By the time we reach
+ * LONG_MAX milliseconds -- 24 days on 32-bit platforms --
+ * continuing to honor slow_down requests seems pretty
+ * pointless anyway.)
+ */
+ int64 interval_ms;
+
+ if (pg_mul_s64_overflow(actx->authz.interval, 1000,
+ &interval_ms)
+ || (interval_ms > LONG_MAX))
+ {
+ interval_ms = LONG_MAX;
+ }
+
+ if (!set_timer(actx, (long) interval_ms))
+ goto error_return;
+ }
/*
* No Curl requests are running, so we can simplify by having
--
2.34.1