libpq: Discard leading and trailing spaces for parameters and values in URIs

Integer values applied a parsing rule through pqParseIntParam() that
made URIs like this one working, even if these include spaces around
values:
"postgresql://localhost:5432/postgres?keepalives=1 &keepalives_idle=1 "

This commit changes the parsing so as spaces before and after parameters
and values are discarded, offering more consistency with the parsing
that already applied to libpq for integer values in URIs.

Note that %20 can be used in a URI for a space character.  ECPGconnect()
has been discarded leading and trailing spaces around parameters and
values that for a long time, as well.  Like f22e84df1d, this is done
as a HEAD-only change.

Reviewed-by: Yuto Sasaki
Discussion: https://postgr.es/m/Zv3oWOfcrHTph7JK@paquier.xyz
This commit is contained in:
Michael Paquier 2024-10-06 18:23:02 +09:00
parent 68dfecbef2
commit 430ce189fc
2 changed files with 54 additions and 6 deletions

View File

@ -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;
}

View File

@ -86,6 +86,24 @@ 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{},
],
[
# Trailing data in parameter.
q{postgresql://host? user user = uri & port = 12345 12 },
q{},
q{libpq_uri_regress: trailing data found: " user user "},
],
[
# Trailing data in value.
q{postgresql://host? user = 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},