diff options
| author | Michael Paquier <michael@paquier.xyz> | 2025-11-04 20:12:48 +0900 |
|---|---|---|
| committer | Michael Paquier <michael@paquier.xyz> | 2025-11-04 20:12:48 +0900 |
| commit | 861af9261035cec7408040d646cba92959ba6f13 (patch) | |
| tree | b1766f2a5c6fdc006ee37745225b97b3d68e70c8 | |
| parent | ad1581d7feaeb1d78a0858703dac1bcb52f600d8 (diff) | |
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
| -rw-r--r-- | src/interfaces/libpq/fe-connect.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index a3d12931fff..19bbc006669 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -501,8 +501,9 @@ static int parseServiceFile(const char *serviceFile, PQExpBuffer errorMessage, bool *group_found); static char *pwdfMatchesString(char *buf, const char *token); -static char *passwordFromFile(const char *hostname, const char *port, const char *dbname, - const char *username, const char *pgpassfile); +static char *passwordFromFile(const char *hostname, const char *port, + const char *dbname, const char *username, + const char *pgpassfile, const char **errmsg); static void pgpassfileWarning(PGconn *conn); static void default_threadlock(int acquire); static bool sslVerifyProtocolVersion(const char *version); @@ -1454,6 +1455,7 @@ pqConnectOptions2(PGconn *conn) * least one of them is guaranteed nonempty by now). */ const char *pwhost = conn->connhost[i].host; + const char *password_errmsg = NULL; if (pwhost == NULL || pwhost[0] == '\0') pwhost = conn->connhost[i].hostaddr; @@ -1463,7 +1465,15 @@ pqConnectOptions2(PGconn *conn) conn->connhost[i].port, conn->dbName, 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; } -/* 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 * -passwordFromFile(const char *hostname, const char *port, const char *dbname, - const char *username, const char *pgpassfile) +passwordFromFile(const char *hostname, const char *port, + const char *dbname, const char *username, + const char *pgpassfile, const char **errmsg) { FILE *fp; #ifndef WIN32 @@ -7953,6 +7969,8 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname, #endif PQExpBufferData buf; + *errmsg = NULL; + if (dbname == NULL || dbname[0] == '\0') 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 */ if (!enlargePQExpBuffer(&buf, 128)) + { + *errmsg = libpq_gettext("out of memory"); break; + } /* Read some data, appending it to what we already have */ 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) { - /* Out of memory. XXX: an error message would be nice. */ + *errmsg = libpq_gettext("out of memory"); return NULL; } |
