Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit ead6eda

Browse files
JelteFCommitfest Bot
authored and
Commitfest Bot
committed
Bump protocol version to 3.2
In preparation of new additions to the protocol in a follow up commit this bumps the minor protocol version number. Instead of bumping the version number to 3.1, which would be the next minor version, we skip that one and bump straight to 3.2. The reason for this is that many PgBouncer releases have, due to an off-by-one bug, reported 3.1 as supported[1]. These versions would interpret 3.1 as equivalent to 3.0. So if we would now add extra messages to the 3.1 protocol, clients would succeed to connect to PgBouncer, but would then cause connection failures when sending such new messages. So instead of bumping to 3.1, we bump the protocol version to 3.2, for which these buggy PgBouncer releases will correctly close the connection at the startup packet. It's a bit strange to skip a version number due to a bug in a third-party application, but PgBouncer is used widely enough that it seems worth it to not cause user confusion when connecting to recent versions of it. Especially since skipping a single minor version number in the protocol versioning doesn't really cost us anything. So, while this is not the most theoretically sound decission, it is the most pragmatic one. [1]: pgbouncer/pgbouncer#1007
1 parent af81259 commit ead6eda

File tree

5 files changed

+117
-21
lines changed

5 files changed

+117
-21
lines changed

doc/src/sgml/libpq.sgml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2388,7 +2388,8 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
23882388

23892389
<para>
23902390
The current supported values are
2391-
<literal>3.0</literal>
2391+
<literal>3.0</literal>,
2392+
<literal>3.2</literal>,
23922393
and <literal>latest</literal>. The <literal>latest</literal> value is
23932394
equivalent to the latest protocol version that is supported by the used
23942395
libpq version, which currently is <literal>3.2</literal>, but this will
@@ -2415,10 +2416,11 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
24152416

24162417
<para>
24172418
The current supported values are
2418-
<literal>3.0</literal>
2419+
<literal>3.0</literal>,
2420+
<literal>3.2</literal>,
24192421
and <literal>latest</literal>. The <literal>latest</literal> value is
24202422
equivalent to the latest protocol version that is supported by the used
2421-
libpq version, which currently is <literal>3.0</literal>, but this will
2423+
libpq version, which currently is <literal>3.2</literal>, but this will
24222424
change in future libpq releases.
24232425
</para>
24242426
</listitem>

src/include/libpq/pqcomm.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,10 @@ is_unixsock_path(const char *path)
9191

9292
/*
9393
* The earliest and latest frontend/backend protocol version supported.
94-
* (Only protocol version 3 is currently supported)
9594
*/
9695

9796
#define PG_PROTOCOL_EARLIEST PG_PROTOCOL(3,0)
98-
#define PG_PROTOCOL_LATEST PG_PROTOCOL(3,0)
97+
#define PG_PROTOCOL_LATEST PG_PROTOCOL(3,2)
9998

10099
typedef uint32 ProtocolVersion; /* FE/BE protocol version number */
101100

src/interfaces/libpq/fe-connect.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8180,6 +8180,15 @@ pqParseProtocolVersion(const char *value, ProtocolVersion *result, PGconn *conn,
81808180
return true;
81818181
}
81828182

8183+
if (strcmp(value, "3.1") == 0)
8184+
{
8185+
conn->status = CONNECTION_BAD;
8186+
libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
8187+
context,
8188+
value);
8189+
return false;
8190+
}
8191+
81838192
major = strtol(value, &end, 10);
81848193
if (*end != '.')
81858194
{

src/interfaces/libpq/fe-protocol3.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1427,7 +1427,13 @@ pqGetNegotiateProtocolVersion3(PGconn *conn)
14271427
libpq_append_conn_error(conn, "received invalid protocol negotiation message: server requests downgrade to pre-3.0 protocol version");
14281428
goto failure;
14291429
}
1430-
1430+
1431+
if (their_version == PG_PROTOCOL(3, 1))
1432+
{
1433+
libpq_append_conn_error(conn, "received invalid protocol negotiation message: server requests downgrade to 3.1 protocol version");
1434+
goto failure;
1435+
}
1436+
14311437
if (num < 0)
14321438
{
14331439
libpq_append_conn_error(conn, "received invalid protocol negotiation message: server reported negative number of unsupported parameters");

src/test/modules/libpq_pipeline/libpq_pipeline.c

Lines changed: 95 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -198,24 +198,15 @@ send_cancellable_query_impl(int line, PGconn *conn, PGconn *monitorConn)
198198
}
199199

200200
/*
201-
* Create a new connection with the same conninfo as the given one.
201+
* Fills keywords and vals, with the same options as the ones in the opts
202+
* linked-list. Returns the length of the filled in list.
202203
*/
203-
static PGconn *
204-
copy_connection(PGconn *conn)
204+
static
205+
int
206+
copy_connection_options(PQconninfoOption *opts, const char **keywords, const char **vals)
205207
{
206-
PGconn *copyConn;
207-
PQconninfoOption *opts = PQconninfo(conn);
208-
const char **keywords;
209-
const char **vals;
210-
int nopts = 1;
211208
int i = 0;
212209

213-
for (PQconninfoOption *opt = opts; opt->keyword != NULL; ++opt)
214-
nopts++;
215-
216-
keywords = pg_malloc(sizeof(char *) * nopts);
217-
vals = pg_malloc(sizeof(char *) * nopts);
218-
219210
for (PQconninfoOption *opt = opts; opt->keyword != NULL; ++opt)
220211
{
221212
if (opt->val)
@@ -225,8 +216,28 @@ copy_connection(PGconn *conn)
225216
i++;
226217
}
227218
}
228-
keywords[i] = vals[i] = NULL;
219+
return i;
220+
}
221+
222+
/*
223+
* Create a new connection with the same conninfo as the given one.
224+
*/
225+
static PGconn *
226+
copy_connection(PGconn *conn)
227+
{
228+
const char **keywords;
229+
const char **vals;
230+
PGconn *copyConn;
231+
PQconninfoOption *opts = PQconninfo(conn);
232+
int nopts = 1; /* 1 for the NULL terminator */
229233

234+
for (PQconninfoOption *opt = opts; opt->keyword != NULL; ++opt)
235+
nopts++;
236+
237+
keywords = pg_malloc0(sizeof(char *) * nopts);
238+
vals = pg_malloc0(sizeof(char *) * nopts);
239+
240+
copy_connection_options(opts, keywords, vals);
230241
copyConn = PQconnectdbParams(keywords, vals, false);
231242

232243
if (PQstatus(copyConn) != CONNECTION_OK)
@@ -1406,6 +1417,72 @@ test_prepared(PGconn *conn)
14061417
fprintf(stderr, "ok\n");
14071418
}
14081419

1420+
static void
1421+
test_protocol_version(PGconn *conn)
1422+
{
1423+
const char **keywords;
1424+
const char **vals;
1425+
int nopts = 2; /* NULL terminator + max_protocol_version */
1426+
PQconninfoOption *opts = PQconninfo(conn);
1427+
int protocol_version;
1428+
int max_protocol_version_index;
1429+
1430+
for (PQconninfoOption *opt = opts; opt->keyword != NULL; ++opt)
1431+
nopts++;
1432+
1433+
keywords = pg_malloc0(sizeof(char *) * nopts);
1434+
vals = pg_malloc0(sizeof(char *) * nopts);
1435+
1436+
max_protocol_version_index = copy_connection_options(opts, keywords, vals);
1437+
1438+
keywords[max_protocol_version_index] = "max_protocol_version";
1439+
vals[max_protocol_version_index] = "3.0";
1440+
1441+
conn = PQconnectdbParams(keywords, vals, false);
1442+
1443+
if (PQstatus(conn) != CONNECTION_OK)
1444+
pg_fatal("Connection to database failed: %s",
1445+
PQerrorMessage(conn));
1446+
1447+
protocol_version = PQfullProtocolVersion(conn);
1448+
if (protocol_version != 30000)
1449+
pg_fatal("expected 30000, got %d", protocol_version);
1450+
1451+
PQfinish(conn);
1452+
1453+
vals[max_protocol_version_index] = "3.1";
1454+
conn = PQconnectdbParams(keywords, vals, false);
1455+
1456+
if (PQstatus(conn) != CONNECTION_BAD)
1457+
pg_fatal("Connecting with max_protocol_version 3.1 should have failed.");
1458+
1459+
PQfinish(conn);
1460+
1461+
vals[max_protocol_version_index] = "3.2";
1462+
conn = PQconnectdbParams(keywords, vals, false);
1463+
1464+
if (PQstatus(conn) != CONNECTION_OK)
1465+
pg_fatal("Connection to database failed: %s",
1466+
PQerrorMessage(conn));
1467+
1468+
protocol_version = PQfullProtocolVersion(conn);
1469+
if (protocol_version != 30002)
1470+
pg_fatal("expected 30002, got %d", protocol_version);
1471+
PQfinish(conn);
1472+
1473+
vals[max_protocol_version_index] = "latest";
1474+
conn = PQconnectdbParams(keywords, vals, false);
1475+
1476+
if (PQstatus(conn) != CONNECTION_OK)
1477+
pg_fatal("Connection to database failed: %s",
1478+
PQerrorMessage(conn));
1479+
1480+
protocol_version = PQfullProtocolVersion(conn);
1481+
if (protocol_version != 30002)
1482+
pg_fatal("expected 30002, got %d", protocol_version);
1483+
PQfinish(conn);
1484+
}
1485+
14091486
/* Notice processor: print notices, and count how many we got */
14101487
static void
14111488
notice_processor(void *arg, const char *message)
@@ -2154,6 +2231,7 @@ print_test_list(void)
21542231
printf("pipeline_idle\n");
21552232
printf("pipelined_insert\n");
21562233
printf("prepared\n");
2234+
printf("protocol_version\n");
21572235
printf("simple_pipeline\n");
21582236
printf("singlerow\n");
21592237
printf("transaction\n");
@@ -2273,6 +2351,8 @@ main(int argc, char **argv)
22732351
test_pipelined_insert(conn, numrows);
22742352
else if (strcmp(testname, "prepared") == 0)
22752353
test_prepared(conn);
2354+
else if (strcmp(testname, "protocol_version") == 0)
2355+
test_protocol_version(conn);
22762356
else if (strcmp(testname, "simple_pipeline") == 0)
22772357
test_simple_pipeline(conn);
22782358
else if (strcmp(testname, "singlerow") == 0)

0 commit comments

Comments
 (0)