On Wed, Oct 02, 2024 at 05:39:31PM -0400, Tom Lane wrote: > Interesting. This is unhappy about the space before a parameter name, > not the space after a parameter value, so it's a different issue.
conninfo_uri_parse_options() parses the URI as a set of option/values, where conninfo_uri_parse_params. If we were to be careful about trailing and leading whitespaces for the parameter names, we need to be careful about the special JDBC cases for "ssl" and "requiressl", meaning that we should add more logic in conninfo_uri_decode() to discard these. That would apply a extra layer of sanity into the values as well. > But it's weird that ecpg takes it while libpq doesn't. Could libecpg > be modifying/reassembling the URI string? I didn't look. ECPGconnect() has some custom logic to discard trailing and leading spaces: /* Skip spaces before keyword */ for (token1 = str; *token1 == ' '; token1++) [...] token1[e] = '\0'; //skips trailing spaces. The argument for libpq where we could be consistent is appealing. How about lifting things in libpq like the attached? I wouldn't backpatch that, but we have tests for URIs and I didn't break anything. -- Michael
From dafde0e2d5382571bfb91339e3f9e9a5530738b0 Mon Sep 17 00:00:00 2001 From: Michael Paquier <mich...@paquier.xyz> Date: Thu, 3 Oct 2024 09:34:01 +0900 Subject: [PATCH] libpq: Count for leading and trailing whitespaces in URIs --- src/interfaces/libpq/fe-connect.c | 42 ++++++++++++++++++++++++++----- src/interfaces/libpq/t/001_uri.pl | 11 ++++++++ 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 64787bea51..2d09ea5afd 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -6763,9 +6763,9 @@ conninfo_uri_parse_params(char *params, static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage) { - char *buf; - char *p; - const char *q = str; + char *buf; /* result */ + char *p; /* output location */ + const char *q = str; /* input location */ buf = malloc(strlen(str) + 1); if (buf == NULL) @@ -6775,13 +6775,23 @@ conninfo_uri_decode(const char *str, PQExpBuffer errorMessage) } p = buf; + /* skip leading whitespaces */ + for (const char *s = q; *s == ' '; s++) + { + q++; + continue; + } + for (;;) { if (*q != '%') { - /* copy and check for NUL terminator */ - if (!(*(p++) = *(q++))) - break; + /* if found a whitespace or NUL, the string ends */ + if (*q == ' ' || *q == '\0') + goto end; + + /* copy character */ + *(p++) = *(q++); } else { @@ -6817,6 +6827,26 @@ conninfo_uri_decode(const char *str, PQExpBuffer errorMessage) } } +end: + + /* skip trailing whitespaces */ + for (const char *s = q; *s == ' '; s++) + { + q++; + continue; + } + + /* Not at the end of the string yet? Fail. */ + if (*q != '\0') + { + libpq_append_error(errorMessage, "trailing data found: \"%s\"", str); + free(buf); + return NULL; + } + + /* Copy NUL terminator */ + *p = '\0'; + return buf; } diff --git a/src/interfaces/libpq/t/001_uri.pl b/src/interfaces/libpq/t/001_uri.pl index 49ea5377e0..a872e973e7 100644 --- a/src/interfaces/libpq/t/001_uri.pl +++ b/src/interfaces/libpq/t/001_uri.pl @@ -86,6 +86,17 @@ my @tests = ( q{user='uri-user' host='host' (inet)}, q{}, ], + [ + # Leading and trailing spaces, works + q{postgresql://host? user = uri-user & port = 12345 }, + q{user='uri-user' host='host' port='12345' (inet)}, + q{}, + ], + [ + q{postgresql://host? host = uri-user & port = 12345 12 }, + q{}, + q{libpq_uri_regress: trailing data found: " 12345 12 "}, + ], [ q{postgresql://host?}, q{host='host' (inet)}, q{}, ], [ q{postgresql://[::1]:12345/db}, -- 2.45.2
signature.asc
Description: PGP signature