1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-09 06:21:09 +03:00

libpq: Improve error handling in passwordFromFile()

Previously, passwordFromFile() returned NULL for valid cases (like no
matching password found) and actual errors (two out-of-memory paths).
This made it impossible for its sole caller, pqConnectOptions2(), to
distinguish between these scenarios and fail the connection
appropriately should an out-of-memory error occur.

This patch extends passwordFromFile() to be able to detect both valid
and failure cases, with an error string given back to the caller of the
function.

Out-of-memory failures unlikely happen in the field, so no backpatch is
done.

Author: Joshua Shanks <jjshanks@gmail.com>
Discussion: https://postgr.es/m/CAOxqWDfihFRmhNVdfu8epYTXQRxkCHSOrg+=-ij2c_X3gW=o3g@mail.gmail.com
This commit is contained in:
Michael Paquier
2025-11-04 20:12:48 +09:00
parent ad1581d7fe
commit 861af92610

View File

@@ -501,8 +501,9 @@ static int parseServiceFile(const char *serviceFile,
PQExpBuffer errorMessage, PQExpBuffer errorMessage,
bool *group_found); bool *group_found);
static char *pwdfMatchesString(char *buf, const char *token); static char *pwdfMatchesString(char *buf, const char *token);
static char *passwordFromFile(const char *hostname, const char *port, const char *dbname, static char *passwordFromFile(const char *hostname, const char *port,
const char *username, const char *pgpassfile); const char *dbname, const char *username,
const char *pgpassfile, const char **errmsg);
static void pgpassfileWarning(PGconn *conn); static void pgpassfileWarning(PGconn *conn);
static void default_threadlock(int acquire); static void default_threadlock(int acquire);
static bool sslVerifyProtocolVersion(const char *version); static bool sslVerifyProtocolVersion(const char *version);
@@ -1454,6 +1455,7 @@ pqConnectOptions2(PGconn *conn)
* least one of them is guaranteed nonempty by now). * least one of them is guaranteed nonempty by now).
*/ */
const char *pwhost = conn->connhost[i].host; const char *pwhost = conn->connhost[i].host;
const char *password_errmsg = NULL;
if (pwhost == NULL || pwhost[0] == '\0') if (pwhost == NULL || pwhost[0] == '\0')
pwhost = conn->connhost[i].hostaddr; pwhost = conn->connhost[i].hostaddr;
@@ -1463,7 +1465,15 @@ pqConnectOptions2(PGconn *conn)
conn->connhost[i].port, conn->connhost[i].port,
conn->dbName, conn->dbName,
conn->pguser, conn->pguser,
conn->pgpassfile); conn->pgpassfile,
&password_errmsg);
if (password_errmsg != NULL)
{
conn->status = CONNECTION_BAD;
libpq_append_conn_error(conn, "%s", password_errmsg);
return false;
}
} }
} }
} }
@@ -7942,10 +7952,16 @@ pwdfMatchesString(char *buf, const char *token)
return NULL; return NULL;
} }
/* Get a password from the password file. Return value is malloc'd. */ /*
* Get a password from the password file. Return value is malloc'd.
*
* On failure, *errmsg is set to an error to be returned. It is
* left NULL on success, or if no password could be found.
*/
static char * static char *
passwordFromFile(const char *hostname, const char *port, const char *dbname, passwordFromFile(const char *hostname, const char *port,
const char *username, const char *pgpassfile) const char *dbname, const char *username,
const char *pgpassfile, const char **errmsg)
{ {
FILE *fp; FILE *fp;
#ifndef WIN32 #ifndef WIN32
@@ -7953,6 +7969,8 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname,
#endif #endif
PQExpBufferData buf; PQExpBufferData buf;
*errmsg = NULL;
if (dbname == NULL || dbname[0] == '\0') if (dbname == NULL || dbname[0] == '\0')
return NULL; return NULL;
@@ -8019,7 +8037,10 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname,
{ {
/* Make sure there's a reasonable amount of room in the buffer */ /* Make sure there's a reasonable amount of room in the buffer */
if (!enlargePQExpBuffer(&buf, 128)) if (!enlargePQExpBuffer(&buf, 128))
{
*errmsg = libpq_gettext("out of memory");
break; break;
}
/* Read some data, appending it to what we already have */ /* Read some data, appending it to what we already have */
if (fgets(buf.data + buf.len, buf.maxlen - buf.len, fp) == NULL) if (fgets(buf.data + buf.len, buf.maxlen - buf.len, fp) == NULL)
@@ -8058,7 +8079,7 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname,
if (!ret) if (!ret)
{ {
/* Out of memory. XXX: an error message would be nice. */ *errmsg = libpq_gettext("out of memory");
return NULL; return NULL;
} }