From a87695e07d6101cdabbd1c20c9749ab84ccd601a Mon Sep 17 00:00:00 2001
From: Jacob Champion <jacob.champion@enterprisedb.com>
Date: Tue, 16 Jun 2026 11:22:25 -0700
Subject: [PATCH v2 2/4] oauth_hook_client: Print the linked libcurl version

Add a --curl-version option to oauth_hook_client, so that 001_server.pl
can easily figure out which version of libcurl we've been configured
against. A subsequent commit will use this information to skip some
newly failing tests.

This is admittedly an odd place to put the logic -- oauth_hook_client
does not otherwise use Curl -- but it avoids introducing a lot of new
temporary code into the back branches for the sake of a workaround. (The
eventual plan is to move this functionality into libpq-oauth after the
PG19 feature freeze lifts.)

Discussion: https://postgr.es/m/CAOYmi%2B%3DkP86t%2BZFFXNQ9G6K4ht7utdmB%3DCzhP%3DZ2wvuBymOTtQ%40mail.gmail.com
Backpatch-through: 18
---
 src/test/modules/oauth_validator/meson.build  |  6 ++-
 src/test/modules/oauth_validator/Makefile     |  5 ++
 .../oauth_validator/oauth_hook_client.c       | 52 +++++++++++++++++++
 3 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/src/test/modules/oauth_validator/meson.build b/src/test/modules/oauth_validator/meson.build
index 506a9894b8d..d7680d73a49 100644
--- a/src/test/modules/oauth_validator/meson.build
+++ b/src/test/modules/oauth_validator/meson.build
@@ -60,7 +60,11 @@ endif
 
 oauth_hook_client = executable('oauth_hook_client',
   oauth_hook_client_sources,
-  dependencies: [frontend_code, libpq],
+  dependencies: [
+    frontend_code,
+    libpq,
+    libcurl,  # for the --curl-version option
+  ],
   kwargs: default_bin_args + {
     'install': false,
   },
diff --git a/src/test/modules/oauth_validator/Makefile b/src/test/modules/oauth_validator/Makefile
index 0b39a88fd9f..5e895214f07 100644
--- a/src/test/modules/oauth_validator/Makefile
+++ b/src/test/modules/oauth_validator/Makefile
@@ -19,6 +19,11 @@ OBJS = $(WIN32RES) oauth_hook_client.o
 PG_CPPFLAGS = -I$(libpq_srcdir)
 PG_LIBS_INTERNAL += $(libpq_pgport)
 
+# for the --curl-version option
+PG_CPPFLAGS += $(LIBCURL_CPPFLAGS)
+PG_LDFLAGS += $(LIBCURL_LDFLAGS)
+PG_LIBS += $(LIBCURL_LDLIBS)
+
 NO_INSTALLCHECK = 1
 
 TAP_TESTS = 1
diff --git a/src/test/modules/oauth_validator/oauth_hook_client.c b/src/test/modules/oauth_validator/oauth_hook_client.c
index 4695d73e8f7..63f295a9217 100644
--- a/src/test/modules/oauth_validator/oauth_hook_client.c
+++ b/src/test/modules/oauth_validator/oauth_hook_client.c
@@ -18,6 +18,10 @@
 
 #include <sys/socket.h>
 
+#if USE_LIBCURL
+#include <curl/curl.h>
+#endif
+
 #include "getopt_long.h"
 #include "libpq-fe.h"
 
@@ -28,6 +32,7 @@ static PostgresPollingStatusType async_cb(PGconn *conn,
 static PostgresPollingStatusType misbehave_cb(PGconn *conn,
 											  PGoauthBearerRequest *req,
 											  pgsocket *altsock);
+static void print_curl_version(void);
 
 static void
 usage(char *argv[])
@@ -47,6 +52,7 @@ usage(char *argv[])
 	printf("  --token TOKEN           use the provided TOKEN value\n");
 	printf("  --error ERRMSG          fail instead, with the given ERRMSG (v2 only)\n");
 	printf("  --stress-async          busy-loop on PQconnectPoll rather than polling\n");
+	printf("  --curl-version          (Curl-enabled builds only) print the version of libcurl\n");
 }
 
 /* --options */
@@ -76,6 +82,7 @@ main(int argc, char *argv[])
 		{"stress-async", no_argument, NULL, 1006},
 		{"expected-issuer", required_argument, NULL, 1007},
 		{"error", required_argument, NULL, 1008},
+		{"curl-version", no_argument, NULL, 1009},
 		{0}
 	};
 
@@ -139,6 +146,10 @@ main(int argc, char *argv[])
 				errmsg = optarg;
 				break;
 
+			case 1009:			/* --curl-version */
+				print_curl_version();
+				return 0;
+
 			default:
 				usage(argv);
 				return 1;
@@ -379,3 +390,44 @@ misbehave_cb(PGconn *conn, PGoauthBearerRequest *req, pgsocket *altsock)
 		exit(1);
 	}
 }
+
+#if USE_LIBCURL
+
+/*
+ * XXX You may wonder why this test executable, which purposely does not make
+ * use of libcurl functionality, is printing out the version of Curl. This is
+ * needed to skip tests in 001_server when we see a known broken version of
+ * libcurl. (Querying the local Curl executable isn't good enough, because that
+ * may not use the same libcurl that we've been configured with.)
+ *
+ * This is only needed for stable branches prior to 20, which can't glean the
+ * libcurl version from trace output.
+ */
+static void
+print_curl_version(void)
+{
+	curl_version_info_data *info;
+
+	if (curl_global_init(CURL_GLOBAL_NOTHING) != CURLE_OK)
+	{
+		fprintf(stderr, "curl_global_init() failed\n");
+		exit(1);
+	}
+
+	info = curl_version_info(CURLVERSION_NOW);
+	printf("libcurl %s (%s)\n",
+		   info->version ? info->version : "version unknown",
+		   info->ssl_version ? info->ssl_version : "no SSL");
+}
+
+#else							/* ! USE_LIBCURL */
+
+static void
+print_curl_version(void)
+{
+	fprintf(stderr,
+			"--curl-version is not supported by this build configuration\n");
+	exit(1);
+}
+
+#endif							/* USE_LIBCURL */
-- 
2.34.1

