In libpq, always append new error messages to conn->errorMessage.

Previously, we had an undisciplined mish-mash of printfPQExpBuffer and
appendPQExpBuffer calls to report errors within libpq.  This commit
establishes a uniform rule that appendPQExpBuffer[Str] should be used.
conn->errorMessage is reset only at the start of an application request,
and then accumulates messages till we're done.  We can remove no less
than three different ad-hoc mechanisms that were used to get the effect
of concatenation of error messages within a sequence of operations.

Although this makes things quite a bit cleaner conceptually, the main
reason to do it is to make the world safer for the multiple-target-host
feature that was added awhile back.  Previously, there were many cases
in which an error occurring during an individual host connection attempt
would wipe out the record of what had happened during previous attempts.
(The reporting is still inadequate, in that it can be hard to tell which
host got the failure, but that seems like a matter for a separate commit.)

Currently, lo_import and lo_export contain exceptions to the "never
use printfPQExpBuffer" rule.  If we changed them, we'd risk reporting
an incidental lo_close failure before the actual read or write
failure, which would be confusing, not least because lo_close happened
after the main failure.  We could improve this by inventing an
internal version of lo_close that doesn't reset the errorMessage; but
we'd also need a version of PQfn() that does that, and it didn't quite
seem worth the trouble for now.

Discussion: https://postgr.es/m/BN6PR05MB3492948E4FD76C156E747E8BC9160@BN6PR05MB3492.namprd05.prod.outlook.com
This commit is contained in:
Tom Lane 2021-01-11 13:12:09 -05:00
parent ce6a71fa53
commit ffa2e46701
14 changed files with 699 additions and 774 deletions

View File

@ -208,14 +208,14 @@ pg_fe_scram_exchange(void *opaq, char *input, int inputlen,
{
if (inputlen == 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("malformed SCRAM message (empty message)\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("malformed SCRAM message (empty message)\n"));
goto error;
}
if (inputlen != strlen(input))
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("malformed SCRAM message (length mismatch)\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("malformed SCRAM message (length mismatch)\n"));
goto error;
}
}
@ -258,15 +258,15 @@ pg_fe_scram_exchange(void *opaq, char *input, int inputlen,
*/
if (!verify_server_signature(state, success))
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not verify server signature\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("could not verify server signature\n"));
goto error;
}
if (!*success)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("incorrect server signature\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("incorrect server signature\n"));
}
*done = true;
state->state = FE_SCRAM_FINISHED;
@ -274,8 +274,8 @@ pg_fe_scram_exchange(void *opaq, char *input, int inputlen,
default:
/* shouldn't happen */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid SCRAM exchange state\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("invalid SCRAM exchange state\n"));
goto error;
}
return;
@ -287,6 +287,11 @@ error:
/*
* Read value for an attribute part of a SCRAM message.
*
* The buffer at **input is destructively modified, and *input is
* advanced over the "attr=value" string and any following comma.
*
* On failure, append an error message to *errorMessage and return NULL.
*/
static char *
read_attr_value(char **input, char attr, PQExpBuffer errorMessage)
@ -296,7 +301,7 @@ read_attr_value(char **input, char attr, PQExpBuffer errorMessage)
if (*begin != attr)
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("malformed SCRAM message (attribute \"%c\" expected)\n"),
attr);
return NULL;
@ -305,7 +310,7 @@ read_attr_value(char **input, char attr, PQExpBuffer errorMessage)
if (*begin != '=')
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("malformed SCRAM message (expected character \"=\" for attribute \"%c\")\n"),
attr);
return NULL;
@ -346,8 +351,8 @@ build_client_first_message(fe_scram_state *state)
*/
if (!pg_strong_random(raw_nonce, SCRAM_RAW_NONCE_LEN))
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not generate nonce\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("could not generate nonce\n"));
return NULL;
}
@ -356,16 +361,16 @@ build_client_first_message(fe_scram_state *state)
state->client_nonce = malloc(encoded_len + 1);
if (state->client_nonce == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return NULL;
}
encoded_len = pg_b64_encode(raw_nonce, SCRAM_RAW_NONCE_LEN,
state->client_nonce, encoded_len);
if (encoded_len < 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not encode nonce\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("could not encode nonce\n"));
return NULL;
}
state->client_nonce[encoded_len] = '\0';
@ -431,8 +436,8 @@ build_client_first_message(fe_scram_state *state)
oom_error:
termPQExpBuffer(&buf);
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return NULL;
}
@ -508,8 +513,8 @@ build_client_final_message(fe_scram_state *state)
free(cbind_data);
free(cbind_input);
termPQExpBuffer(&buf);
printfPQExpBuffer(&conn->errorMessage,
"could not encode cbind data for channel binding\n");
appendPQExpBufferStr(&conn->errorMessage,
"could not encode cbind data for channel binding\n");
return NULL;
}
buf.len += encoded_cbind_len;
@ -523,8 +528,8 @@ build_client_final_message(fe_scram_state *state)
* Shouldn't happen.
*/
termPQExpBuffer(&buf);
printfPQExpBuffer(&conn->errorMessage,
"channel binding not supported by this build\n");
appendPQExpBufferStr(&conn->errorMessage,
"channel binding not supported by this build\n");
return NULL;
#endif /* HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH */
}
@ -553,8 +558,8 @@ build_client_final_message(fe_scram_state *state)
client_proof))
{
termPQExpBuffer(&buf);
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not calculate client proof\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("could not calculate client proof\n"));
return NULL;
}
@ -569,8 +574,8 @@ build_client_final_message(fe_scram_state *state)
if (encoded_len < 0)
{
termPQExpBuffer(&buf);
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not encode client proof\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("could not encode client proof\n"));
return NULL;
}
buf.len += encoded_len;
@ -585,8 +590,8 @@ build_client_final_message(fe_scram_state *state)
oom_error:
termPQExpBuffer(&buf);
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return NULL;
}
@ -606,8 +611,8 @@ read_server_first_message(fe_scram_state *state, char *input)
state->server_first_message = strdup(input);
if (state->server_first_message == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return false;
}
@ -616,7 +621,7 @@ read_server_first_message(fe_scram_state *state, char *input)
&conn->errorMessage);
if (nonce == NULL)
{
/* read_attr_value() has generated an error string */
/* read_attr_value() has appended an error string */
return false;
}
@ -624,31 +629,31 @@ read_server_first_message(fe_scram_state *state, char *input)
if (strlen(nonce) < strlen(state->client_nonce) ||
memcmp(nonce, state->client_nonce, strlen(state->client_nonce)) != 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid SCRAM response (nonce mismatch)\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("invalid SCRAM response (nonce mismatch)\n"));
return false;
}
state->nonce = strdup(nonce);
if (state->nonce == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return false;
}
encoded_salt = read_attr_value(&input, 's', &conn->errorMessage);
if (encoded_salt == NULL)
{
/* read_attr_value() has generated an error string */
/* read_attr_value() has appended an error string */
return false;
}
decoded_salt_len = pg_b64_dec_len(strlen(encoded_salt));
state->salt = malloc(decoded_salt_len);
if (state->salt == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return false;
}
state->saltlen = pg_b64_decode(encoded_salt,
@ -657,28 +662,28 @@ read_server_first_message(fe_scram_state *state, char *input)
decoded_salt_len);
if (state->saltlen < 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("malformed SCRAM message (invalid salt)\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("malformed SCRAM message (invalid salt)\n"));
return false;
}
iterations_str = read_attr_value(&input, 'i', &conn->errorMessage);
if (iterations_str == NULL)
{
/* read_attr_value() has generated an error string */
/* read_attr_value() has appended an error string */
return false;
}
state->iterations = strtol(iterations_str, &endptr, 10);
if (*endptr != '\0' || state->iterations < 1)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("malformed SCRAM message (invalid iteration count)\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("malformed SCRAM message (invalid iteration count)\n"));
return false;
}
if (*input != '\0')
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("malformed SCRAM message (garbage at end of server-first-message)\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("malformed SCRAM message (garbage at end of server-first-message)\n"));
return true;
}
@ -697,8 +702,8 @@ read_server_final_message(fe_scram_state *state, char *input)
state->server_final_message = strdup(input);
if (!state->server_final_message)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return false;
}
@ -708,7 +713,12 @@ read_server_final_message(fe_scram_state *state, char *input)
char *errmsg = read_attr_value(&input, 'e',
&conn->errorMessage);
printfPQExpBuffer(&conn->errorMessage,
if (errmsg == NULL)
{
/* read_attr_value() has appended an error message */
return false;
}
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("error received from server in SCRAM exchange: %s\n"),
errmsg);
return false;
@ -719,20 +729,20 @@ read_server_final_message(fe_scram_state *state, char *input)
&conn->errorMessage);
if (encoded_server_signature == NULL)
{
/* read_attr_value() has generated an error message */
/* read_attr_value() has appended an error message */
return false;
}
if (*input != '\0')
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("malformed SCRAM message (garbage at end of server-final-message)\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("malformed SCRAM message (garbage at end of server-final-message)\n"));
server_signature_len = pg_b64_dec_len(strlen(encoded_server_signature));
decoded_server_signature = malloc(server_signature_len);
if (!decoded_server_signature)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return false;
}
@ -743,8 +753,8 @@ read_server_final_message(fe_scram_state *state, char *input)
if (server_signature_len != SCRAM_KEY_LEN)
{
free(decoded_server_signature);
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("malformed SCRAM message (invalid server signature)\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("malformed SCRAM message (invalid server signature)\n"));
return false;
}
memcpy(state->ServerSignature, decoded_server_signature, SCRAM_KEY_LEN);

View File

@ -72,7 +72,7 @@ pg_GSS_continue(PGconn *conn, int payloadlen)
ginbuf.value = malloc(payloadlen);
if (!ginbuf.value)
{
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory allocating GSSAPI buffer (%d)\n"),
payloadlen);
return STATUS_ERROR;
@ -154,15 +154,15 @@ pg_GSS_startup(PGconn *conn, int payloadlen)
if (!(host && host[0] != '\0'))
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("host name must be specified\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("host name must be specified\n"));
return STATUS_ERROR;
}
if (conn->gctx)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("duplicate GSS authentication request\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("duplicate GSS authentication request\n"));
return STATUS_ERROR;
}
@ -195,10 +195,10 @@ pg_SSPI_error(PGconn *conn, const char *mprefix, SECURITY_STATUS r)
FORMAT_MESSAGE_FROM_SYSTEM,
NULL, r, 0,
sysmsg, sizeof(sysmsg), NULL) == 0)
printfPQExpBuffer(&conn->errorMessage, "%s: SSPI error %x\n",
appendPQExpBuffer(&conn->errorMessage, "%s: SSPI error %x\n",
mprefix, (unsigned int) r);
else
printfPQExpBuffer(&conn->errorMessage, "%s: %s (%x)\n",
appendPQExpBuffer(&conn->errorMessage, "%s: %s (%x)\n",
mprefix, sysmsg, (unsigned int) r);
}
@ -226,7 +226,7 @@ pg_SSPI_continue(PGconn *conn, int payloadlen)
inputbuf = malloc(payloadlen);
if (!inputbuf)
{
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory allocating SSPI buffer (%d)\n"),
payloadlen);
return STATUS_ERROR;
@ -286,7 +286,8 @@ pg_SSPI_continue(PGconn *conn, int payloadlen)
conn->sspictx = malloc(sizeof(CtxtHandle));
if (conn->sspictx == NULL)
{
printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return STATUS_ERROR;
}
memcpy(conn->sspictx, &newContext, sizeof(CtxtHandle));
@ -305,7 +306,8 @@ pg_SSPI_continue(PGconn *conn, int payloadlen)
* authentication. Keep check in case it shows up with other
* authentication methods later.
*/
printfPQExpBuffer(&conn->errorMessage, "SSPI returned invalid number of output buffers\n");
appendPQExpBufferStr(&conn->errorMessage,
"SSPI returned invalid number of output buffers\n");
return STATUS_ERROR;
}
@ -345,8 +347,8 @@ pg_SSPI_startup(PGconn *conn, int use_negotiate, int payloadlen)
if (conn->sspictx)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("duplicate SSPI authentication request\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("duplicate SSPI authentication request\n"));
return STATUS_ERROR;
}
@ -356,7 +358,8 @@ pg_SSPI_startup(PGconn *conn, int use_negotiate, int payloadlen)
conn->sspicred = malloc(sizeof(CredHandle));
if (conn->sspicred == NULL)
{
printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return STATUS_ERROR;
}
@ -384,14 +387,15 @@ pg_SSPI_startup(PGconn *conn, int use_negotiate, int payloadlen)
*/
if (!(host && host[0] != '\0'))
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("host name must be specified\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("host name must be specified\n"));
return STATUS_ERROR;
}
conn->sspitarget = malloc(strlen(conn->krbsrvname) + strlen(host) + 2);
if (!conn->sspitarget)
{
printfPQExpBuffer(&conn->errorMessage, libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return STATUS_ERROR;
}
sprintf(conn->sspitarget, "%s/%s", conn->krbsrvname, host);
@ -425,15 +429,15 @@ pg_SASL_init(PGconn *conn, int payloadlen)
if (conn->channel_binding[0] == 'r' && /* require */
!conn->ssl_in_use)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("channel binding required, but SSL not in use\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("channel binding required, but SSL not in use\n"));
goto error;
}
if (conn->sasl_state)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("duplicate SASL authentication request\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("duplicate SASL authentication request\n"));
goto error;
}
@ -448,8 +452,8 @@ pg_SASL_init(PGconn *conn, int payloadlen)
{
if (pqGets(&mechanism_buf, conn))
{
printfPQExpBuffer(&conn->errorMessage,
"fe_sendauth: invalid authentication request from server: invalid list of authentication mechanisms\n");
appendPQExpBufferStr(&conn->errorMessage,
"fe_sendauth: invalid authentication request from server: invalid list of authentication mechanisms\n");
goto error;
}
if (PQExpBufferDataBroken(mechanism_buf))
@ -488,8 +492,8 @@ pg_SASL_init(PGconn *conn, int payloadlen)
*/
if (conn->channel_binding[0] == 'r') /* require */
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("channel binding is required, but client does not support it\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("channel binding is required, but client does not support it\n"));
goto error;
}
#endif
@ -505,8 +509,8 @@ pg_SASL_init(PGconn *conn, int payloadlen)
* the client and server supported it. The SCRAM exchange
* checks for that, to prevent downgrade attacks.
*/
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("server offered SCRAM-SHA-256-PLUS authentication over a non-SSL connection\n"));
goto error;
}
}
@ -517,16 +521,16 @@ pg_SASL_init(PGconn *conn, int payloadlen)
if (!selected_mechanism)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("none of the server's SASL authentication mechanisms are supported\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("none of the server's SASL authentication mechanisms are supported\n"));
goto error;
}
if (conn->channel_binding[0] == 'r' && /* require */
strcmp(selected_mechanism, SCRAM_SHA_256_PLUS_NAME) != 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("channel binding is required, but server did not offer an authentication method that supports channel binding\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("channel binding is required, but server did not offer an authentication method that supports channel binding\n"));
goto error;
}
@ -546,8 +550,8 @@ pg_SASL_init(PGconn *conn, int payloadlen)
password = conn->pgpass;
if (password == NULL || password[0] == '\0')
{
printfPQExpBuffer(&conn->errorMessage,
PQnoPasswordSupplied);
appendPQExpBufferStr(&conn->errorMessage,
PQnoPasswordSupplied);
goto error;
}
@ -607,8 +611,8 @@ oom_error:
termPQExpBuffer(&mechanism_buf);
if (initialresponse)
free(initialresponse);
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return STATUS_ERROR;
}
@ -631,7 +635,7 @@ pg_SASL_continue(PGconn *conn, int payloadlen, bool final)
challenge = malloc(payloadlen + 1);
if (!challenge)
{
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory allocating SASL buffer (%d)\n"),
payloadlen);
return STATUS_ERROR;
@ -656,8 +660,8 @@ pg_SASL_continue(PGconn *conn, int payloadlen, bool final)
if (outputlen != 0)
free(output);
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("AuthenticationSASLFinal received from server, but SASL authentication was not completed\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("AuthenticationSASLFinal received from server, but SASL authentication was not completed\n"));
return STATUS_ERROR;
}
if (outputlen != 0)
@ -726,15 +730,15 @@ pg_local_sendauth(PGconn *conn)
{
char sebuf[PG_STRERROR_R_BUFLEN];
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
"pg_local_sendauth: sendmsg: %s\n",
strerror_r(errno, sebuf, sizeof(sebuf)));
return STATUS_ERROR;
}
return STATUS_OK;
#else
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SCM_CRED authentication method not supported\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("SCM_CRED authentication method not supported\n"));
return STATUS_ERROR;
#endif
}
@ -766,8 +770,8 @@ pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
crypt_pwd = malloc(2 * (MD5_PASSWD_LEN + 1));
if (!crypt_pwd)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return STATUS_ERROR;
}
@ -832,14 +836,14 @@ check_expected_areq(AuthRequest areq, PGconn *conn)
case AUTH_REQ_OK:
if (!pg_fe_scram_channel_bound(conn->sasl_state))
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("channel binding required, but server authenticated client without channel binding\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("channel binding required, but server authenticated client without channel binding\n"));
result = false;
}
break;
default:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("channel binding required but not supported by server's authentication request\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("channel binding required but not supported by server's authentication request\n"));
result = false;
break;
}
@ -862,6 +866,8 @@ check_expected_areq(AuthRequest areq, PGconn *conn)
int
pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn)
{
int oldmsglen;
if (!check_expected_areq(areq, conn))
return STATUS_ERROR;
@ -871,13 +877,13 @@ pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn)
break;
case AUTH_REQ_KRB4:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("Kerberos 4 authentication not supported\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("Kerberos 4 authentication not supported\n"));
return STATUS_ERROR;
case AUTH_REQ_KRB5:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("Kerberos 5 authentication not supported\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("Kerberos 5 authentication not supported\n"));
return STATUS_ERROR;
#if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
@ -947,8 +953,8 @@ pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn)
/* No GSSAPI *or* SSPI support */
case AUTH_REQ_GSS:
case AUTH_REQ_GSS_CONT:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("GSSAPI authentication not supported\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("GSSAPI authentication not supported\n"));
return STATUS_ERROR;
#endif /* defined(ENABLE_GSS) || defined(ENABLE_SSPI) */
@ -979,16 +985,16 @@ pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn)
*/
#if !defined(ENABLE_GSS)
case AUTH_REQ_SSPI:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSPI authentication not supported\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("SSPI authentication not supported\n"));
return STATUS_ERROR;
#endif /* !define(ENABLE_GSS) */
#endif /* ENABLE_SSPI */
case AUTH_REQ_CRYPT:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("Crypt authentication not supported\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("Crypt authentication not supported\n"));
return STATUS_ERROR;
case AUTH_REQ_MD5:
@ -1002,14 +1008,14 @@ pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn)
password = conn->pgpass;
if (password == NULL || password[0] == '\0')
{
printfPQExpBuffer(&conn->errorMessage,
PQnoPasswordSupplied);
appendPQExpBufferStr(&conn->errorMessage,
PQnoPasswordSupplied);
return STATUS_ERROR;
}
if (pg_password_sendauth(conn, password, areq) != STATUS_OK)
{
printfPQExpBuffer(&conn->errorMessage,
"fe_sendauth: error sending password authentication\n");
appendPQExpBufferStr(&conn->errorMessage,
"fe_sendauth: error sending password authentication\n");
return STATUS_ERROR;
}
break;
@ -1032,17 +1038,18 @@ pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn)
case AUTH_REQ_SASL_FIN:
if (conn->sasl_state == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
"fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
appendPQExpBufferStr(&conn->errorMessage,
"fe_sendauth: invalid authentication request from server: AUTH_REQ_SASL_CONT without AUTH_REQ_SASL\n");
return STATUS_ERROR;
}
oldmsglen = conn->errorMessage.len;
if (pg_SASL_continue(conn, payloadlen,
(areq == AUTH_REQ_SASL_FIN)) != STATUS_OK)
{
/* Use error message, if set already */
if (conn->errorMessage.len == 0)
printfPQExpBuffer(&conn->errorMessage,
"fe_sendauth: error in SASL authentication\n");
/* Use this message if pg_SASL_continue didn't supply one */
if (conn->errorMessage.len == oldmsglen)
appendPQExpBufferStr(&conn->errorMessage,
"fe_sendauth: error in SASL authentication\n");
return STATUS_ERROR;
}
break;
@ -1053,7 +1060,7 @@ pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn)
break;
default:
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("authentication method %u not supported\n"), areq);
return STATUS_ERROR;
}
@ -1067,7 +1074,7 @@ pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn)
*
* Returns a pointer to malloc'd space containing whatever name the user
* has authenticated to the system. If there is an error, return NULL,
* and put a suitable error message in *errorMessage if that's not NULL.
* and append a suitable error message to *errorMessage if that's not NULL.
*/
char *
pg_fe_getauthname(PQExpBuffer errorMessage)
@ -1100,7 +1107,7 @@ pg_fe_getauthname(PQExpBuffer errorMessage)
if (GetUserName(username, &namesize))
name = username;
else if (errorMessage)
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("user name lookup failure: error code %lu\n"),
GetLastError());
#else
@ -1110,12 +1117,12 @@ pg_fe_getauthname(PQExpBuffer errorMessage)
else if (errorMessage)
{
if (pwerr != 0)
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("could not look up local user ID %d: %s\n"),
(int) user_id,
strerror_r(pwerr, pwdbuf, sizeof(pwdbuf)));
else
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("local user with ID %d does not exist\n"),
(int) user_id);
}
@ -1125,8 +1132,8 @@ pg_fe_getauthname(PQExpBuffer errorMessage)
{
result = strdup(name);
if (result == NULL && errorMessage)
printfPQExpBuffer(errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(errorMessage,
libpq_gettext("out of memory\n"));
}
pgunlock_thread();
@ -1196,6 +1203,8 @@ PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user,
if (!conn)
return NULL;
resetPQExpBuffer(&conn->errorMessage);
/* If no algorithm was given, ask the server. */
if (algorithm == NULL)
{
@ -1217,8 +1226,8 @@ PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user,
if (PQntuples(res) != 1 || PQnfields(res) != 1)
{
PQclear(res);
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("unexpected shape of result set returned for SHOW\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("unexpected shape of result set returned for SHOW\n"));
return NULL;
}
val = PQgetvalue(res, 0, 0);
@ -1226,8 +1235,8 @@ PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user,
if (strlen(val) > MAX_ALGORITHM_NAME_LEN)
{
PQclear(res);
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("password_encryption value too long\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("password_encryption value too long\n"));
return NULL;
}
strcpy(algobuf, val);
@ -1266,15 +1275,15 @@ PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user,
}
else
{
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("unrecognized password encryption algorithm \"%s\"\n"),
algorithm);
return NULL;
}
if (!crypt_pwd)
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return crypt_pwd;
}

View File

@ -755,7 +755,9 @@ PQconnectStartParams(const char *const *keywords,
PQconninfoOption *connOptions;
/*
* Allocate memory for the conn structure
* Allocate memory for the conn structure. Note that we also expect this
* to initialize conn->errorMessage to empty. All subsequent steps during
* connection initialization will only append to that buffer.
*/
conn = makeEmptyPGconn();
if (conn == NULL)
@ -831,7 +833,9 @@ PQconnectStart(const char *conninfo)
PGconn *conn;
/*
* Allocate memory for the conn structure
* Allocate memory for the conn structure. Note that we also expect this
* to initialize conn->errorMessage to empty. All subsequent steps during
* connection initialization will only append to that buffer.
*/
conn = makeEmptyPGconn();
if (conn == NULL)
@ -889,8 +893,8 @@ fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
*connmember = strdup(tmp);
if (*connmember == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return false;
}
}
@ -1072,7 +1076,7 @@ connectOptions2(PGconn *conn)
if (more || i != conn->nconnhost)
{
conn->status = CONNECTION_BAD;
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not match %d host names to %d hostaddr values\n"),
count_comma_separated_elems(conn->pghost), conn->nconnhost);
return false;
@ -1153,7 +1157,7 @@ connectOptions2(PGconn *conn)
else if (more || i != conn->nconnhost)
{
conn->status = CONNECTION_BAD;
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not match %d port numbers to %d hosts\n"),
count_comma_separated_elems(conn->pgport), conn->nconnhost);
return false;
@ -1246,7 +1250,7 @@ connectOptions2(PGconn *conn)
&& strcmp(conn->channel_binding, "require") != 0)
{
conn->status = CONNECTION_BAD;
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid %s value: \"%s\"\n"),
"channel_binding", conn->channel_binding);
return false;
@ -1272,7 +1276,7 @@ connectOptions2(PGconn *conn)
&& strcmp(conn->sslmode, "verify-full") != 0)
{
conn->status = CONNECTION_BAD;
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid %s value: \"%s\"\n"),
"sslmode", conn->sslmode);
return false;
@ -1293,7 +1297,7 @@ connectOptions2(PGconn *conn)
case 'r': /* "require" */
case 'v': /* "verify-ca" or "verify-full" */
conn->status = CONNECTION_BAD;
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("sslmode value \"%s\" invalid when SSL support is not compiled in\n"),
conn->sslmode);
return false;
@ -1314,7 +1318,7 @@ connectOptions2(PGconn *conn)
if (!sslVerifyProtocolVersion(conn->ssl_min_protocol_version))
{
conn->status = CONNECTION_BAD;
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid %s value: \"%s\"\n"),
"ssl_min_protocol_version",
conn->ssl_min_protocol_version);
@ -1323,7 +1327,7 @@ connectOptions2(PGconn *conn)
if (!sslVerifyProtocolVersion(conn->ssl_max_protocol_version))
{
conn->status = CONNECTION_BAD;
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid %s value: \"%s\"\n"),
"ssl_max_protocol_version",
conn->ssl_max_protocol_version);
@ -1341,8 +1345,8 @@ connectOptions2(PGconn *conn)
conn->ssl_max_protocol_version))
{
conn->status = CONNECTION_BAD;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid SSL protocol version range\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("invalid SSL protocol version range\n"));
return false;
}
@ -1356,7 +1360,7 @@ connectOptions2(PGconn *conn)
strcmp(conn->gssencmode, "require") != 0)
{
conn->status = CONNECTION_BAD;
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid %s value: \"%s\"\n"),
"gssencmode",
conn->gssencmode);
@ -1366,7 +1370,7 @@ connectOptions2(PGconn *conn)
if (strcmp(conn->gssencmode, "require") == 0)
{
conn->status = CONNECTION_BAD;
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("gssencmode value \"%s\" invalid when GSSAPI support is not compiled in\n"),
conn->gssencmode);
return false;
@ -1401,7 +1405,7 @@ connectOptions2(PGconn *conn)
&& strcmp(conn->target_session_attrs, "read-write") != 0)
{
conn->status = CONNECTION_BAD;
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid %s value: \"%s\"\n"),
"target_settion_attrs",
conn->target_session_attrs);
@ -1420,8 +1424,8 @@ connectOptions2(PGconn *conn)
oom_error:
conn->status = CONNECTION_BAD;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return false;
}
@ -1487,7 +1491,9 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
PGconn *conn;
/*
* Allocate memory for the conn structure
* Allocate memory for the conn structure. Note that we also expect this
* to initialize conn->errorMessage to empty. All subsequent steps during
* connection initialization will only append to that buffer.
*/
conn = makeEmptyPGconn();
if (conn == NULL)
@ -1596,8 +1602,8 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
oom_error:
conn->status = CONNECTION_BAD;
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return conn;
}
@ -2017,8 +2023,8 @@ connectDBStart(PGconn *conn)
*/
if (!pg_link_canary_is_frontend())
{
printfPQExpBuffer(&conn->errorMessage,
"libpq is incorrectly linked to backend functions\n");
appendPQExpBufferStr(&conn->errorMessage,
"libpq is incorrectly linked to backend functions\n");
goto connect_errReturn;
}
@ -2026,14 +2032,6 @@ connectDBStart(PGconn *conn)
conn->inStart = conn->inCursor = conn->inEnd = 0;
conn->outCount = 0;
/*
* Ensure errorMessage is empty, too. PQconnectPoll will append messages
* to it in the process of scanning for a working server. Thus, if we
* fail to connect to multiple hosts, the final error message will include
* details about each failure.
*/
resetPQExpBuffer(&conn->errorMessage);
/*
* Set up to try to connect to the first host. (Setting whichhost = -1 is
* a bit of a cheat, but PQconnectPoll will advance it to 0 before
@ -2139,12 +2137,6 @@ connectDBComplete(PGconn *conn)
switch (flag)
{
case PGRES_POLLING_OK:
/*
* Reset stored error messages since we now have a working
* connection
*/
resetPQExpBuffer(&conn->errorMessage);
return 1; /* success! */
case PGRES_POLLING_READING:
@ -2189,46 +2181,6 @@ connectDBComplete(PGconn *conn)
}
}
/*
* This subroutine saves conn->errorMessage, which will be restored back by
* restoreErrorMessage subroutine. Returns false on OOM failure.
*/
static bool
saveErrorMessage(PGconn *conn, PQExpBuffer savedMessage)
{
initPQExpBuffer(savedMessage);
appendPQExpBufferStr(savedMessage,
conn->errorMessage.data);
if (PQExpBufferBroken(savedMessage))
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return false;
}
/* Clear whatever is in errorMessage now */
resetPQExpBuffer(&conn->errorMessage);
return true;
}
/*
* Restores saved error messages back to conn->errorMessage, prepending them
* to whatever is in conn->errorMessage already. (This does the right thing
* if anything's been added to conn->errorMessage since saveErrorMessage.)
*/
static void
restoreErrorMessage(PGconn *conn, PQExpBuffer savedMessage)
{
appendPQExpBufferStr(savedMessage, conn->errorMessage.data);
resetPQExpBuffer(&conn->errorMessage);
appendPQExpBufferStr(&conn->errorMessage, savedMessage->data);
/* If any step above hit OOM, just report that */
if (PQExpBufferBroken(savedMessage) ||
PQExpBufferBroken(&conn->errorMessage))
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
termPQExpBuffer(savedMessage);
}
/* ----------------
* PQconnectPoll
*
@ -2264,7 +2216,6 @@ PQconnectPoll(PGconn *conn)
PGresult *res;
char sebuf[PG_STRERROR_R_BUFLEN];
int optval;
PQExpBufferData savedMessage;
if (conn == NULL)
return PGRES_POLLING_FAILED;
@ -2954,12 +2905,8 @@ keep_going: /* We will come back to here until there is
EnvironmentOptions);
if (!startpacket)
{
/*
* will not appendbuffer here, since it's likely to also
* run out of memory
*/
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
goto error_return;
}
@ -3448,7 +3395,6 @@ keep_going: /* We will come back to here until there is
* avoid the Kerberos code doing a hostname look-up.
*/
res = pg_fe_sendauth(areq, msgLength, conn);
conn->errorMessage.len = strlen(conn->errorMessage.data);
/* OK, we have processed the message; mark data consumed */
conn->inStart = conn->inCursor;
@ -3576,24 +3522,16 @@ keep_going: /* We will come back to here until there is
strcmp(conn->target_session_attrs, "read-write") == 0)
{
/*
* Save existing error messages across the PQsendQuery
* attempt. This is necessary because PQsendQuery is
* going to reset conn->errorMessage, so we would lose
* error messages related to previous hosts we have tried
* and failed to connect to.
* We use PQsendQueryContinue so that conn->errorMessage
* does not get cleared. We need to preserve any error
* messages related to previous hosts we have tried and
* failed to connect to.
*/
if (!saveErrorMessage(conn, &savedMessage))
goto error_return;
conn->status = CONNECTION_OK;
if (!PQsendQuery(conn,
"SHOW transaction_read_only"))
{
restoreErrorMessage(conn, &savedMessage);
if (!PQsendQueryContinue(conn,
"SHOW transaction_read_only"))
goto error_return;
}
conn->status = CONNECTION_CHECK_WRITABLE;
restoreErrorMessage(conn, &savedMessage);
return PGRES_POLLING_READING;
}
@ -3673,20 +3611,13 @@ keep_going: /* We will come back to here until there is
const char *displayed_host;
const char *displayed_port;
if (!saveErrorMessage(conn, &savedMessage))
goto error_return;
conn->status = CONNECTION_OK;
if (!PQconsumeInput(conn))
{
restoreErrorMessage(conn, &savedMessage);
goto error_return;
}
if (PQisBusy(conn))
{
conn->status = CONNECTION_CHECK_WRITABLE;
restoreErrorMessage(conn, &savedMessage);
return PGRES_POLLING_READING;
}
@ -3701,7 +3632,6 @@ keep_going: /* We will come back to here until there is
{
/* Not writable; fail this connection. */
PQclear(res);
restoreErrorMessage(conn, &savedMessage);
/* Append error report to conn->errorMessage. */
if (conn->connhost[conn->whichhost].type == CHT_HOST_ADDRESS)
@ -3732,7 +3662,6 @@ keep_going: /* We will come back to here until there is
/* Session is read-write, so we're good. */
PQclear(res);
termPQExpBuffer(&savedMessage);
/*
* Finish reading any remaining messages before being
@ -3748,7 +3677,6 @@ keep_going: /* We will come back to here until there is
*/
if (res)
PQclear(res);
restoreErrorMessage(conn, &savedMessage);
/* Append error report to conn->errorMessage. */
if (conn->connhost[conn->whichhost].type == CHT_HOST_ADDRESS)
@ -4157,6 +4085,9 @@ closePGconn(PGconn *conn)
/*
* Close the connection, reset all transient state, flush I/O buffers.
* Note that this includes clearing conn->errorMessage; we're no longer
* interested in any failures associated with the old connection, and we
* want a clean slate for any new connection attempt.
*/
pqDropConnection(conn, true);
conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
@ -4212,7 +4143,7 @@ PQreset(PGconn *conn)
conn->events[i].passThrough))
{
conn->status = CONNECTION_BAD;
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n"),
conn->events[i].name);
break;
@ -4272,7 +4203,7 @@ PQresetPoll(PGconn *conn)
conn->events[i].passThrough))
{
conn->status = CONNECTION_BAD;
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("PGEventProc \"%s\" failed during PGEVT_CONNRESET event\n"),
conn->events[i].name);
return PGRES_POLLING_FAILED;
@ -4569,7 +4500,7 @@ pqPacketSend(PGconn *conn, char pack_type,
* 2 if a connection could not be established, and
* 3 if a fatal error occurred.
*
* An error message is returned in the third argument for return codes 1 and 3.
* An error message is appended to *errorMessage for return codes 1 and 3.
*/
static int
ldapServiceLookup(const char *purl, PQconninfoOption *options,
@ -4607,7 +4538,7 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
if ((url = strdup(purl)) == NULL)
{
printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
appendPQExpBufferStr(errorMessage, libpq_gettext("out of memory\n"));
return 3;
}
@ -4619,7 +4550,7 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
if (pg_strncasecmp(url, LDAP_URL, strlen(LDAP_URL)) != 0)
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("invalid LDAP URL \"%s\": scheme must be ldap://\n"), purl);
free(url);
return 3;
@ -4634,7 +4565,7 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
p = strchr(url + strlen(LDAP_URL), '/');
if (p == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("invalid LDAP URL \"%s\": missing distinguished name\n"),
purl);
free(url);
@ -4646,7 +4577,7 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
/* attribute */
if ((p = strchr(dn, '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("invalid LDAP URL \"%s\": must have exactly one attribute\n"),
purl);
free(url);
@ -4658,7 +4589,9 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
/* scope */
if ((p = strchr(attrs[0], '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
{
printfPQExpBuffer(errorMessage, libpq_gettext("invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n"), purl);
appendPQExpBuffer(errorMessage,
libpq_gettext("invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n"),
purl);
free(url);
return 3;
}
@ -4668,8 +4601,9 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
/* filter */
if ((p = strchr(scopestr, '?')) == NULL || *(p + 1) == '\0' || *(p + 1) == '?')
{
printfPQExpBuffer(errorMessage,
libpq_gettext("invalid LDAP URL \"%s\": no filter\n"), purl);
appendPQExpBuffer(errorMessage,
libpq_gettext("invalid LDAP URL \"%s\": no filter\n"),
purl);
free(url);
return 3;
}
@ -4689,7 +4623,7 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
lport = strtol(portstr, &endptr, 10);
if (*portstr == '\0' || *endptr != '\0' || errno || lport < 0 || lport > 65535)
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("invalid LDAP URL \"%s\": invalid port number\n"),
purl);
free(url);
@ -4701,7 +4635,7 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
/* Allow only one attribute */
if (strchr(attrs[0], ',') != NULL)
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("invalid LDAP URL \"%s\": must have exactly one attribute\n"),
purl);
free(url);
@ -4717,7 +4651,9 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
scope = LDAP_SCOPE_SUBTREE;
else
{
printfPQExpBuffer(errorMessage, libpq_gettext("invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n"), purl);
appendPQExpBuffer(errorMessage,
libpq_gettext("invalid LDAP URL \"%s\": must have search scope (base/one/sub)\n"),
purl);
free(url);
return 3;
}
@ -4725,8 +4661,8 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
/* initialize LDAP structure */
if ((ld = ldap_init(hostname, port)) == NULL)
{
printfPQExpBuffer(errorMessage,
libpq_gettext("could not create LDAP structure\n"));
appendPQExpBufferStr(errorMessage,
libpq_gettext("could not create LDAP structure\n"));
free(url);
return 3;
}
@ -4801,7 +4737,7 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
{
if (res != NULL)
ldap_msgfree(res);
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("lookup on LDAP server failed: %s\n"),
ldap_err2string(rc));
ldap_unbind(ld);
@ -4812,9 +4748,9 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
/* complain if there was not exactly one result */
if ((rc = ldap_count_entries(ld, res)) != 1)
{
printfPQExpBuffer(errorMessage,
rc ? libpq_gettext("more than one entry found on LDAP lookup\n")
: libpq_gettext("no entry found on LDAP lookup\n"));
appendPQExpBufferStr(errorMessage,
rc ? libpq_gettext("more than one entry found on LDAP lookup\n")
: libpq_gettext("no entry found on LDAP lookup\n"));
ldap_msgfree(res);
ldap_unbind(ld);
free(url);
@ -4825,8 +4761,8 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
if ((entry = ldap_first_entry(ld, res)) == NULL)
{
/* should never happen */
printfPQExpBuffer(errorMessage,
libpq_gettext("no entry found on LDAP lookup\n"));
appendPQExpBufferStr(errorMessage,
libpq_gettext("no entry found on LDAP lookup\n"));
ldap_msgfree(res);
ldap_unbind(ld);
free(url);
@ -4836,8 +4772,8 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
/* get values */
if ((values = ldap_get_values_len(ld, entry, attrs[0])) == NULL)
{
printfPQExpBuffer(errorMessage,
libpq_gettext("attribute has no values on LDAP lookup\n"));
appendPQExpBufferStr(errorMessage,
libpq_gettext("attribute has no values on LDAP lookup\n"));
ldap_msgfree(res);
ldap_unbind(ld);
free(url);
@ -4849,8 +4785,8 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
if (values[0] == NULL)
{
printfPQExpBuffer(errorMessage,
libpq_gettext("attribute has no values on LDAP lookup\n"));
appendPQExpBufferStr(errorMessage,
libpq_gettext("attribute has no values on LDAP lookup\n"));
ldap_value_free_len(values);
ldap_unbind(ld);
return 1;
@ -4862,8 +4798,8 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
size += values[i]->bv_len + 1;
if ((result = malloc(size)) == NULL)
{
printfPQExpBuffer(errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(errorMessage,
libpq_gettext("out of memory\n"));
ldap_value_free_len(values);
ldap_unbind(ld);
return 3;
@ -4901,7 +4837,7 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
}
else if (ld_is_nl_cr(*p))
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"),
optname);
free(result);
@ -4920,7 +4856,7 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
}
else if (!ld_is_sp_tab(*p))
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"),
optname);
free(result);
@ -4981,8 +4917,8 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
options[i].val = strdup(optval);
if (!options[i].val)
{
printfPQExpBuffer(errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(errorMessage,
libpq_gettext("out of memory\n"));
free(result);
return 3;
}
@ -4993,7 +4929,7 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
}
if (!found_keyword)
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("invalid connection option \"%s\"\n"),
optname);
free(result);
@ -5009,8 +4945,8 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
if (state == 5 || state == 6)
{
printfPQExpBuffer(errorMessage,
libpq_gettext("unterminated quoted string in connection info string\n"));
appendPQExpBufferStr(errorMessage,
libpq_gettext("unterminated quoted string in connection info string\n"));
return 3;
}
@ -5090,7 +5026,7 @@ next_file:
last_file:
if (!group_found)
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("definition of service \"%s\" not found\n"), service);
return 3;
}
@ -5117,7 +5053,7 @@ parseServiceFile(const char *serviceFile,
f = fopen(serviceFile, "r");
if (f == NULL)
{
printfPQExpBuffer(errorMessage, libpq_gettext("service file \"%s\" not found\n"),
appendPQExpBuffer(errorMessage, libpq_gettext("service file \"%s\" not found\n"),
serviceFile);
return 1;
}
@ -5193,7 +5129,7 @@ parseServiceFile(const char *serviceFile,
val = strchr(line, '=');
if (val == NULL)
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("syntax error in service file \"%s\", line %d\n"),
serviceFile,
linenr);
@ -5204,7 +5140,7 @@ parseServiceFile(const char *serviceFile,
if (strcmp(key, "service") == 0)
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("nested service specifications not supported in service file \"%s\", line %d\n"),
serviceFile,
linenr);
@ -5225,8 +5161,8 @@ parseServiceFile(const char *serviceFile,
options[i].val = strdup(val);
if (!options[i].val)
{
printfPQExpBuffer(errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(errorMessage,
libpq_gettext("out of memory\n"));
result = 3;
goto exit;
}
@ -5237,7 +5173,7 @@ parseServiceFile(const char *serviceFile,
if (!found_keyword)
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("syntax error in service file \"%s\", line %d\n"),
serviceFile,
linenr);
@ -5307,8 +5243,8 @@ conninfo_init(PQExpBuffer errorMessage)
options = (PQconninfoOption *) malloc(sizeof(PQconninfoOption) * sizeof(PQconninfoOptions) / sizeof(PQconninfoOptions[0]));
if (options == NULL)
{
printfPQExpBuffer(errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(errorMessage,
libpq_gettext("out of memory\n"));
return NULL;
}
opt_dest = options;
@ -5328,7 +5264,7 @@ conninfo_init(PQExpBuffer errorMessage)
* Connection string parser
*
* Returns a malloc'd PQconninfoOption array, if parsing is successful.
* Otherwise, NULL is returned and an error message is left in errorMessage.
* Otherwise, NULL is returned and an error message is added to errorMessage.
*
* If use_defaults is true, default values are filled in (from a service file,
* environment variables, etc).
@ -5406,8 +5342,8 @@ conninfo_parse(const char *conninfo, PQExpBuffer errorMessage,
/* Need a modifiable copy of the input string */
if ((buf = strdup(conninfo)) == NULL)
{
printfPQExpBuffer(errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(errorMessage,
libpq_gettext("out of memory\n"));
PQconninfoFree(options);
return NULL;
}
@ -5445,7 +5381,7 @@ conninfo_parse(const char *conninfo, PQExpBuffer errorMessage,
/* Check that there is a following '=' */
if (*cp != '=')
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"),
pname);
PQconninfoFree(options);
@ -5494,8 +5430,8 @@ conninfo_parse(const char *conninfo, PQExpBuffer errorMessage,
{
if (*cp == '\0')
{
printfPQExpBuffer(errorMessage,
libpq_gettext("unterminated quoted string in connection info string\n"));
appendPQExpBufferStr(errorMessage,
libpq_gettext("unterminated quoted string in connection info string\n"));
PQconninfoFree(options);
free(buf);
return NULL;
@ -5551,7 +5487,7 @@ conninfo_parse(const char *conninfo, PQExpBuffer errorMessage,
*
* If successful, a malloc'd PQconninfoOption array is returned.
* If not successful, NULL is returned and an error message is
* left in errorMessage.
* appended to errorMessage.
* Defaults are supplied (from a service file, environment variables, etc)
* for unspecified options, but only if use_defaults is true.
*
@ -5630,7 +5566,7 @@ conninfo_array_parse(const char *const *keywords, const char *const *values,
/* Check for invalid connection option */
if (option->keyword == NULL)
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("invalid connection option \"%s\"\n"),
pname);
PQconninfoFree(options);
@ -5662,8 +5598,8 @@ conninfo_array_parse(const char *const *keywords, const char *const *values,
options[k].val = strdup(str_option->val);
if (!options[k].val)
{
printfPQExpBuffer(errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(errorMessage,
libpq_gettext("out of memory\n"));
PQconninfoFree(options);
PQconninfoFree(dbname_options);
return NULL;
@ -5691,8 +5627,8 @@ conninfo_array_parse(const char *const *keywords, const char *const *values,
option->val = strdup(pvalue);
if (!option->val)
{
printfPQExpBuffer(errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(errorMessage,
libpq_gettext("out of memory\n"));
PQconninfoFree(options);
PQconninfoFree(dbname_options);
return NULL;
@ -5763,8 +5699,8 @@ conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
if (!option->val)
{
if (errorMessage)
printfPQExpBuffer(errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(errorMessage,
libpq_gettext("out of memory\n"));
return false;
}
continue;
@ -5787,8 +5723,8 @@ conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
if (!option->val)
{
if (errorMessage)
printfPQExpBuffer(errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(errorMessage,
libpq_gettext("out of memory\n"));
return false;
}
continue;
@ -5805,8 +5741,8 @@ conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
if (!option->val)
{
if (errorMessage)
printfPQExpBuffer(errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(errorMessage,
libpq_gettext("out of memory\n"));
return false;
}
continue;
@ -5906,8 +5842,8 @@ conninfo_uri_parse_options(PQconninfoOption *options, const char *uri,
initPQExpBuffer(&portbuf);
if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
{
printfPQExpBuffer(errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(errorMessage,
libpq_gettext("out of memory\n"));
goto cleanup;
}
@ -5915,8 +5851,8 @@ conninfo_uri_parse_options(PQconninfoOption *options, const char *uri,
buf = strdup(uri);
if (buf == NULL)
{
printfPQExpBuffer(errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(errorMessage,
libpq_gettext("out of memory\n"));
goto cleanup;
}
start = buf;
@ -5926,7 +5862,7 @@ conninfo_uri_parse_options(PQconninfoOption *options, const char *uri,
if (prefix_len == 0)
{
/* Should never happen */
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("invalid URI propagated to internal parser routine: \"%s\"\n"),
uri);
goto cleanup;
@ -6003,14 +5939,14 @@ conninfo_uri_parse_options(PQconninfoOption *options, const char *uri,
++p;
if (!*p)
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"\n"),
uri);
goto cleanup;
}
if (p == host)
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("IPv6 host address may not be empty in URI: \"%s\"\n"),
uri);
goto cleanup;
@ -6025,7 +5961,7 @@ conninfo_uri_parse_options(PQconninfoOption *options, const char *uri,
*/
if (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"\n"),
*p, (int) (p - buf + 1), uri);
goto cleanup;
@ -6142,6 +6078,7 @@ conninfo_uri_parse_params(char *params,
char *value = NULL;
char *p = params;
bool malloced = false;
int oldmsglen;
/*
* Scan the params string for '=' and '&', marking the end of keyword
@ -6154,7 +6091,7 @@ conninfo_uri_parse_params(char *params,
/* Was there '=' already? */
if (value != NULL)
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("extra key/value separator \"=\" in URI query parameter: \"%s\"\n"),
keyword);
return false;
@ -6174,7 +6111,7 @@ conninfo_uri_parse_params(char *params,
/* Was there '=' at all? */
if (value == NULL)
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("missing key/value separator \"=\" in URI query parameter: \"%s\"\n"),
keyword);
return false;
@ -6220,12 +6157,13 @@ conninfo_uri_parse_params(char *params,
* otherwise. At this point both keyword and value are not
* URI-encoded.
*/
oldmsglen = errorMessage->len;
if (!conninfo_storeval(connOptions, keyword, value,
errorMessage, true, false))
{
/* Insert generic message if conninfo_storeval didn't give one. */
if (errorMessage->len == 0)
printfPQExpBuffer(errorMessage,
if (errorMessage->len == oldmsglen)
appendPQExpBuffer(errorMessage,
libpq_gettext("invalid URI query parameter: \"%s\"\n"),
keyword);
/* And fail. */
@ -6272,7 +6210,7 @@ conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
buf = malloc(strlen(str) + 1);
if (buf == NULL)
{
printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
appendPQExpBufferStr(errorMessage, libpq_gettext("out of memory\n"));
return NULL;
}
p = buf;
@ -6299,7 +6237,7 @@ conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
*/
if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("invalid percent-encoded token: \"%s\"\n"),
str);
free(buf);
@ -6309,7 +6247,7 @@ conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
c = (hi << 4) | lo;
if (c == 0)
{
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("forbidden value %%00 in percent-encoded value: \"%s\"\n"),
str);
free(buf);
@ -6404,7 +6342,7 @@ conninfo_storeval(PQconninfoOption *connOptions,
if (option == NULL)
{
if (!ignoreMissing)
printfPQExpBuffer(errorMessage,
appendPQExpBuffer(errorMessage,
libpq_gettext("invalid connection option \"%s\"\n"),
keyword);
return NULL;
@ -6422,7 +6360,7 @@ conninfo_storeval(PQconninfoOption *connOptions,
value_copy = strdup(value);
if (value_copy == NULL)
{
printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
appendPQExpBufferStr(errorMessage, libpq_gettext("out of memory\n"));
return NULL;
}
}
@ -6469,7 +6407,10 @@ PQconninfo(PGconn *conn)
if (conn == NULL)
return NULL;
/* We don't actually report any errors here, but callees want a buffer */
/*
* We don't actually report any errors here, but callees want a buffer,
* and we prefer not to trash the conn's errorMessage.
*/
initPQExpBuffer(&errorBuf);
if (PQExpBufferDataBroken(errorBuf))
return NULL; /* out of memory already :-( */

View File

@ -53,7 +53,8 @@ static bool static_std_strings = false;
static PGEvent *dupEvents(PGEvent *events, int count, size_t *memSize);
static bool pqAddTuple(PGresult *res, PGresAttValue *tup,
const char **errmsgp);
static bool PQsendQueryStart(PGconn *conn);
static int PQsendQueryInternal(PGconn *conn, const char *query, bool newQuery);
static bool PQsendQueryStart(PGconn *conn, bool newQuery);
static int PQsendQueryGuts(PGconn *conn,
const char *command,
const char *stmtName,
@ -667,25 +668,6 @@ pqSetResultError(PGresult *res, const char *msg)
res->errMsg = NULL;
}
/*
* pqCatenateResultError -
* concatenate a new error message to the one already in a PGresult
*/
void
pqCatenateResultError(PGresult *res, const char *msg)
{
PQExpBufferData errorBuf;
if (!res || !msg)
return;
initPQExpBuffer(&errorBuf);
if (res->errMsg)
appendPQExpBufferStr(&errorBuf, res->errMsg);
appendPQExpBufferStr(&errorBuf, msg);
pqSetResultError(res, errorBuf.data);
termPQExpBuffer(&errorBuf);
}
/*
* PQclear -
* free's the memory associated with a PGresult
@ -759,68 +741,46 @@ pqClearAsyncResult(PGconn *conn)
/*
* This subroutine deletes any existing async result, sets conn->result
* to a PGresult with status PGRES_FATAL_ERROR, and stores the current
* contents of conn->errorMessage into that result. It differs from a
* plain call on PQmakeEmptyPGresult() in that if there is already an
* async result with status PGRES_FATAL_ERROR, the current error message
* is APPENDED to the old error message instead of replacing it. This
* behavior lets us report multiple error conditions properly, if necessary.
* (An example where this is needed is when the backend sends an 'E' message
* and immediately closes the connection --- we want to report both the
* backend error and the connection closure error.)
* contents of conn->errorMessage into that result.
*/
void
pqSaveErrorResult(PGconn *conn)
{
/*
* If no old async result, just let PQmakeEmptyPGresult make one. Likewise
* if old result is not an error message.
*/
if (conn->result == NULL ||
conn->result->resultStatus != PGRES_FATAL_ERROR ||
conn->result->errMsg == NULL)
{
pqClearAsyncResult(conn);
conn->result = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
}
else
{
/* Else, concatenate error message to existing async result. */
pqCatenateResultError(conn->result, conn->errorMessage.data);
}
pqClearAsyncResult(conn);
conn->result = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
}
/*
* As above, and append conn->write_err_msg to whatever other error we have.
* This is used when we've detected a write failure and have exhausted our
* chances of reporting something else instead.
* As above, after appending conn->write_err_msg to whatever other error we
* have. This is used when we've detected a write failure and have exhausted
* our chances of reporting something else instead.
*/
static void
pqSaveWriteError(PGconn *conn)
{
/*
* Ensure conn->result is an error result, and add anything in
* conn->errorMessage to it.
* If write_err_msg is null because of previous strdup failure, do what we
* can. (It's likely our machinations here will get OOM failures as well,
* but might as well try.)
*/
pqSaveErrorResult(conn);
/*
* Now append write_err_msg to that. If it's null because of previous
* strdup failure, do what we can. (It's likely our machinations here are
* all getting OOM failures as well, but ...)
*/
if (conn->write_err_msg && conn->write_err_msg[0] != '\0')
pqCatenateResultError(conn->result, conn->write_err_msg);
if (conn->write_err_msg)
{
appendPQExpBufferStr(&conn->errorMessage, conn->write_err_msg);
/* Avoid possibly appending the same message twice */
conn->write_err_msg[0] = '\0';
}
else
pqCatenateResultError(conn->result,
libpq_gettext("write to server failed\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("write to server failed\n"));
pqSaveErrorResult(conn);
}
/*
* This subroutine prepares an async result object for return to the caller.
* If there is not already an async result object, build an error object
* using whatever is in conn->errorMessage. In any case, clear the async
* result storage and make sure PQerrorMessage will agree with the result's
* error string.
* result storage.
*/
PGresult *
pqPrepareAsyncResult(PGconn *conn)
@ -835,16 +795,6 @@ pqPrepareAsyncResult(PGconn *conn)
res = conn->result;
if (!res)
res = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
else
{
/*
* Make sure PQerrorMessage agrees with result; it could be different
* if we have concatenated messages.
*/
resetPQExpBuffer(&conn->errorMessage);
appendPQExpBufferStr(&conn->errorMessage,
PQresultErrorMessage(res));
}
/*
* Replace conn->result with next_result, if any. In the normal case
@ -1229,18 +1179,33 @@ fail:
*
* Returns: 1 if successfully submitted
* 0 if error (conn->errorMessage is set)
*
* PQsendQueryContinue is a non-exported version that behaves identically
* except that it doesn't reset conn->errorMessage.
*/
int
PQsendQuery(PGconn *conn, const char *query)
{
if (!PQsendQueryStart(conn))
return PQsendQueryInternal(conn, query, true);
}
int
PQsendQueryContinue(PGconn *conn, const char *query)
{
return PQsendQueryInternal(conn, query, false);
}
static int
PQsendQueryInternal(PGconn *conn, const char *query, bool newQuery)
{
if (!PQsendQueryStart(conn, newQuery))
return 0;
/* check the argument */
if (!query)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("command string is a null pointer\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("command string is a null pointer\n"));
return 0;
}
@ -1291,20 +1256,20 @@ PQsendQueryParams(PGconn *conn,
const int *paramFormats,
int resultFormat)
{
if (!PQsendQueryStart(conn))
if (!PQsendQueryStart(conn, true))
return 0;
/* check the arguments */
if (!command)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("command string is a null pointer\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("command string is a null pointer\n"));
return 0;
}
if (nParams < 0 || nParams > 65535)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("number of parameters must be between 0 and 65535\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("number of parameters must be between 0 and 65535\n"));
return 0;
}
@ -1331,34 +1296,34 @@ PQsendPrepare(PGconn *conn,
const char *stmtName, const char *query,
int nParams, const Oid *paramTypes)
{
if (!PQsendQueryStart(conn))
if (!PQsendQueryStart(conn, true))
return 0;
/* check the arguments */
if (!stmtName)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("statement name is a null pointer\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("statement name is a null pointer\n"));
return 0;
}
if (!query)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("command string is a null pointer\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("command string is a null pointer\n"));
return 0;
}
if (nParams < 0 || nParams > 65535)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("number of parameters must be between 0 and 65535\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("number of parameters must be between 0 and 65535\n"));
return 0;
}
/* This isn't gonna work on a 2.0 server */
if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("function requires at least protocol version 3.0\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("function requires at least protocol version 3.0\n"));
return 0;
}
@ -1432,20 +1397,20 @@ PQsendQueryPrepared(PGconn *conn,
const int *paramFormats,
int resultFormat)
{
if (!PQsendQueryStart(conn))
if (!PQsendQueryStart(conn, true))
return 0;
/* check the arguments */
if (!stmtName)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("statement name is a null pointer\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("statement name is a null pointer\n"));
return 0;
}
if (nParams < 0 || nParams > 65535)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("number of parameters must be between 0 and 65535\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("number of parameters must be between 0 and 65535\n"));
return 0;
}
@ -1464,26 +1429,29 @@ PQsendQueryPrepared(PGconn *conn,
* Common startup code for PQsendQuery and sibling routines
*/
static bool
PQsendQueryStart(PGconn *conn)
PQsendQueryStart(PGconn *conn, bool newQuery)
{
if (!conn)
return false;
/* clear the error string */
resetPQExpBuffer(&conn->errorMessage);
/*
* If this is the beginning of a query cycle, reset the error buffer.
*/
if (newQuery)
resetPQExpBuffer(&conn->errorMessage);
/* Don't try to send if we know there's no live connection. */
if (conn->status != CONNECTION_OK)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("no connection to the server\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("no connection to the server\n"));
return false;
}
/* Can't send while already busy, either. */
if (conn->asyncStatus != PGASYNC_IDLE)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("another command is already in progress\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("another command is already in progress\n"));
return false;
}
@ -1520,8 +1488,8 @@ PQsendQueryGuts(PGconn *conn,
/* This isn't gonna work on a 2.0 server */
if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("function requires at least protocol version 3.0\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("function requires at least protocol version 3.0\n"));
return 0;
}
@ -1596,8 +1564,8 @@ PQsendQueryGuts(PGconn *conn,
nbytes = paramLengths[i];
else
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("length must be given for binary parameter\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("length must be given for binary parameter\n"));
goto sendFailed;
}
}
@ -1859,7 +1827,7 @@ PQgetResult(PGconn *conn)
res = getCopyResult(conn, PGRES_COPY_BOTH);
break;
default:
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("unexpected asyncStatus: %d\n"),
(int) conn->asyncStatus);
res = PQmakeEmptyPGresult(conn, PGRES_FATAL_ERROR);
@ -1879,7 +1847,7 @@ PQgetResult(PGconn *conn)
if (!res->events[i].proc(PGEVT_RESULTCREATE, &evt,
res->events[i].passThrough))
{
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("PGEventProc \"%s\" failed during PGEVT_RESULTCREATE event\n"),
res->events[i].name);
pqSetResultError(res, conn->errorMessage.data);
@ -2025,6 +1993,11 @@ PQexecStart(PGconn *conn)
if (!conn)
return false;
/*
* Since this is the beginning of a query cycle, reset the error buffer.
*/
resetPQExpBuffer(&conn->errorMessage);
/*
* Silently discard any prior query result that application didn't eat.
* This is probably poor design, but it's here for backward compatibility.
@ -2047,8 +2020,8 @@ PQexecStart(PGconn *conn)
else
{
/* In older protocols we have to punt */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("COPY IN state must be terminated first\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("COPY IN state must be terminated first\n"));
return false;
}
}
@ -2067,16 +2040,16 @@ PQexecStart(PGconn *conn)
else
{
/* In older protocols we have to punt */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("COPY OUT state must be terminated first\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("COPY OUT state must be terminated first\n"));
return false;
}
}
else if (resultStatus == PGRES_COPY_BOTH)
{
/* We don't allow PQexec during COPY BOTH */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("PQexec not allowed during COPY BOTH\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("PQexec not allowed during COPY BOTH\n"));
return false;
}
/* check for loss of connection, too */
@ -2099,8 +2072,9 @@ PQexecFinish(PGconn *conn)
/*
* For backwards compatibility, return the last result if there are more
* than one --- but merge error messages if we get more than one error
* result.
* than one. (We used to have logic here to concatenate successive error
* messages, but now that happens automatically, since conn->errorMessage
* will continue to accumulate errors throughout this loop.)
*
* We have to stop if we see copy in/out/both, however. We will resume
* parsing after application performs the data transfer.
@ -2111,23 +2085,7 @@ PQexecFinish(PGconn *conn)
while ((result = PQgetResult(conn)) != NULL)
{
if (lastResult)
{
if (lastResult->resultStatus == PGRES_FATAL_ERROR &&
result->resultStatus == PGRES_FATAL_ERROR)
{
pqCatenateResultError(lastResult, result->errMsg);
PQclear(result);
result = lastResult;
/*
* Make sure PQerrorMessage agrees with concatenated result
*/
resetPQExpBuffer(&conn->errorMessage);
appendPQExpBufferStr(&conn->errorMessage, result->errMsg);
}
else
PQclear(lastResult);
}
PQclear(lastResult);
lastResult = result;
if (result->resultStatus == PGRES_COPY_IN ||
result->resultStatus == PGRES_COPY_OUT ||
@ -2223,14 +2181,14 @@ PQsendDescribe(PGconn *conn, char desc_type, const char *desc_target)
if (!desc_target)
desc_target = "";
if (!PQsendQueryStart(conn))
if (!PQsendQueryStart(conn, true))
return 0;
/* This isn't gonna work on a 2.0 server */
if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("function requires at least protocol version 3.0\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("function requires at least protocol version 3.0\n"));
return 0;
}
@ -2321,8 +2279,8 @@ PQputCopyData(PGconn *conn, const char *buffer, int nbytes)
if (conn->asyncStatus != PGASYNC_COPY_IN &&
conn->asyncStatus != PGASYNC_COPY_BOTH)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("no COPY in progress\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("no COPY in progress\n"));
return -1;
}
@ -2388,8 +2346,8 @@ PQputCopyEnd(PGconn *conn, const char *errormsg)
if (conn->asyncStatus != PGASYNC_COPY_IN &&
conn->asyncStatus != PGASYNC_COPY_BOTH)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("no COPY in progress\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("no COPY in progress\n"));
return -1;
}
@ -2431,8 +2389,8 @@ PQputCopyEnd(PGconn *conn, const char *errormsg)
if (errormsg)
{
/* Oops, no way to do this in 2.0 */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("function requires at least protocol version 3.0\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("function requires at least protocol version 3.0\n"));
return -1;
}
else
@ -2450,7 +2408,6 @@ PQputCopyEnd(PGconn *conn, const char *errormsg)
conn->asyncStatus = PGASYNC_COPY_OUT;
else
conn->asyncStatus = PGASYNC_BUSY;
resetPQExpBuffer(&conn->errorMessage);
/* Try to flush data */
if (pqFlush(conn) < 0)
@ -2478,8 +2435,8 @@ PQgetCopyData(PGconn *conn, char **buffer, int async)
if (conn->asyncStatus != PGASYNC_COPY_OUT &&
conn->asyncStatus != PGASYNC_COPY_BOTH)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("no COPY in progress\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("no COPY in progress\n"));
return -2;
}
if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
@ -2662,14 +2619,16 @@ PQfn(PGconn *conn,
if (!conn)
return NULL;
/* clear the error string */
/*
* Since this is the beginning of a query cycle, reset the error buffer.
*/
resetPQExpBuffer(&conn->errorMessage);
if (conn->sock == PGINVALID_SOCKET || conn->asyncStatus != PGASYNC_IDLE ||
conn->result != NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("connection in wrong state\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("connection in wrong state\n"));
return NULL;
}
@ -3246,7 +3205,11 @@ PQsetnonblocking(PGconn *conn, int arg)
* need to flush the send queue at this point in order to guarantee proper
* behavior. this is ok because either they are making a transition _from_
* or _to_ blocking mode, either way we can block them.
*
* Clear errorMessage in case pqFlush adds to it.
*/
resetPQExpBuffer(&conn->errorMessage);
/* if we are going from blocking to non-blocking flush here */
if (pqFlush(conn))
return -1;
@ -3388,8 +3351,8 @@ PQescapeStringInternal(PGconn *conn,
if (error)
*error = 1;
if (conn)
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("incomplete multibyte character\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("incomplete multibyte character\n"));
for (; i < len; i++)
{
if (((size_t) (target - to)) / 2 >= length)
@ -3419,6 +3382,9 @@ PQescapeStringConn(PGconn *conn,
*error = 1;
return 0;
}
resetPQExpBuffer(&conn->errorMessage);
return PQescapeStringInternal(conn, to, from, length, error,
conn->client_encoding,
conn->std_strings);
@ -3455,6 +3421,8 @@ PQescapeInternal(PGconn *conn, const char *str, size_t len, bool as_ident)
if (!conn)
return NULL;
resetPQExpBuffer(&conn->errorMessage);
/* Scan the string for characters that must be escaped. */
for (s = str; (s - str) < len && *s != '\0'; ++s)
{
@ -3472,8 +3440,8 @@ PQescapeInternal(PGconn *conn, const char *str, size_t len, bool as_ident)
/* Multibyte character overruns allowable length. */
if ((s - str) + charlen > len || memchr(s, 0, charlen) != NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("incomplete multibyte character\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("incomplete multibyte character\n"));
return NULL;
}
@ -3490,8 +3458,8 @@ PQescapeInternal(PGconn *conn, const char *str, size_t len, bool as_ident)
result = rp = (char *) malloc(result_size);
if (rp == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return NULL;
}
@ -3655,8 +3623,8 @@ PQescapeByteaInternal(PGconn *conn,
if (rp == NULL)
{
if (conn)
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return NULL;
}
@ -3717,6 +3685,9 @@ PQescapeByteaConn(PGconn *conn,
{
if (!conn)
return NULL;
resetPQExpBuffer(&conn->errorMessage);
return PQescapeByteaInternal(conn, from, from_length, to_length,
conn->std_strings,
(conn->sversion >= 90000));

View File

@ -46,7 +46,6 @@ void
pg_GSS_error(const char *mprefix, PGconn *conn,
OM_uint32 maj_stat, OM_uint32 min_stat)
{
resetPQExpBuffer(&conn->errorMessage);
appendPQExpBuffer(&conn->errorMessage, "%s:", mprefix);
pg_GSS_error_int(&conn->errorMessage, maj_stat, GSS_C_GSS_CODE);
appendPQExpBufferChar(&conn->errorMessage, ':');
@ -94,8 +93,8 @@ pg_GSS_load_servicename(PGconn *conn)
host = PQhost(conn);
if (!(host && host[0] != '\0'))
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("host name must be specified\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("host name must be specified\n"));
return STATUS_ERROR;
}
@ -107,8 +106,8 @@ pg_GSS_load_servicename(PGconn *conn)
temp_gbuf.value = (char *) malloc(maxlen);
if (!temp_gbuf.value)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return STATUS_ERROR;
}
snprintf(temp_gbuf.value, maxlen, "%s@%s",

View File

@ -61,11 +61,8 @@ lo_open(PGconn *conn, Oid lobjId, int mode)
PQArgBlock argv[2];
PGresult *res;
if (conn == NULL || conn->lobjfuncs == NULL)
{
if (lo_initialize(conn) < 0)
return -1;
}
if (lo_initialize(conn) < 0)
return -1;
argv[0].isint = 1;
argv[0].len = 4;
@ -103,11 +100,8 @@ lo_close(PGconn *conn, int fd)
int retval;
int result_len;
if (conn == NULL || conn->lobjfuncs == NULL)
{
if (lo_initialize(conn) < 0)
return -1;
}
if (lo_initialize(conn) < 0)
return -1;
argv[0].isint = 1;
argv[0].len = 4;
@ -141,17 +135,15 @@ lo_truncate(PGconn *conn, int fd, size_t len)
int retval;
int result_len;
if (conn == NULL || conn->lobjfuncs == NULL)
{
if (lo_initialize(conn) < 0)
return -1;
}
if (lo_initialize(conn) < 0)
return -1;
/* Must check this on-the-fly because it's not there pre-8.3 */
if (conn->lobjfuncs->fn_lo_truncate == 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function lo_truncate\n"));
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function %s\n"),
"lo_truncate");
return -1;
}
@ -166,8 +158,8 @@ lo_truncate(PGconn *conn, int fd, size_t len)
*/
if (len > (size_t) INT_MAX)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("argument of lo_truncate exceeds integer range\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("argument of lo_truncate exceeds integer range\n"));
return -1;
}
@ -209,16 +201,14 @@ lo_truncate64(PGconn *conn, int fd, pg_int64 len)
int retval;
int result_len;
if (conn == NULL || conn->lobjfuncs == NULL)
{
if (lo_initialize(conn) < 0)
return -1;
}
if (lo_initialize(conn) < 0)
return -1;
if (conn->lobjfuncs->fn_lo_truncate64 == 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function lo_truncate64\n"));
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function %s\n"),
"lo_truncate64");
return -1;
}
@ -261,11 +251,8 @@ lo_read(PGconn *conn, int fd, char *buf, size_t len)
PGresult *res;
int result_len;
if (conn == NULL || conn->lobjfuncs == NULL)
{
if (lo_initialize(conn) < 0)
return -1;
}
if (lo_initialize(conn) < 0)
return -1;
/*
* Long ago, somebody thought it'd be a good idea to declare this function
@ -275,8 +262,8 @@ lo_read(PGconn *conn, int fd, char *buf, size_t len)
*/
if (len > (size_t) INT_MAX)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("argument of lo_read exceeds integer range\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("argument of lo_read exceeds integer range\n"));
return -1;
}
@ -316,11 +303,8 @@ lo_write(PGconn *conn, int fd, const char *buf, size_t len)
int result_len;
int retval;
if (conn == NULL || conn->lobjfuncs == NULL)
{
if (lo_initialize(conn) < 0)
return -1;
}
if (lo_initialize(conn) < 0)
return -1;
/*
* Long ago, somebody thought it'd be a good idea to declare this function
@ -330,8 +314,8 @@ lo_write(PGconn *conn, int fd, const char *buf, size_t len)
*/
if (len > (size_t) INT_MAX)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("argument of lo_write exceeds integer range\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("argument of lo_write exceeds integer range\n"));
return -1;
}
@ -369,11 +353,8 @@ lo_lseek(PGconn *conn, int fd, int offset, int whence)
int retval;
int result_len;
if (conn == NULL || conn->lobjfuncs == NULL)
{
if (lo_initialize(conn) < 0)
return -1;
}
if (lo_initialize(conn) < 0)
return -1;
argv[0].isint = 1;
argv[0].len = 4;
@ -413,16 +394,14 @@ lo_lseek64(PGconn *conn, int fd, pg_int64 offset, int whence)
pg_int64 retval;
int result_len;
if (conn == NULL || conn->lobjfuncs == NULL)
{
if (lo_initialize(conn) < 0)
return -1;
}
if (lo_initialize(conn) < 0)
return -1;
if (conn->lobjfuncs->fn_lo_lseek64 == 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function lo_lseek64\n"));
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function %s\n"),
"lo_lseek64");
return -1;
}
@ -469,11 +448,8 @@ lo_creat(PGconn *conn, int mode)
int retval;
int result_len;
if (conn == NULL || conn->lobjfuncs == NULL)
{
if (lo_initialize(conn) < 0)
return InvalidOid;
}
if (lo_initialize(conn) < 0)
return InvalidOid;
argv[0].isint = 1;
argv[0].len = 4;
@ -508,17 +484,15 @@ lo_create(PGconn *conn, Oid lobjId)
int retval;
int result_len;
if (conn == NULL || conn->lobjfuncs == NULL)
{
if (lo_initialize(conn) < 0)
return InvalidOid;
}
if (lo_initialize(conn) < 0)
return InvalidOid;
/* Must check this on-the-fly because it's not there pre-8.1 */
if (conn->lobjfuncs->fn_lo_create == 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function lo_create\n"));
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function %s\n"),
"lo_create");
return InvalidOid;
}
@ -552,11 +526,8 @@ lo_tell(PGconn *conn, int fd)
PGresult *res;
int result_len;
if (conn == NULL || conn->lobjfuncs == NULL)
{
if (lo_initialize(conn) < 0)
return -1;
}
if (lo_initialize(conn) < 0)
return -1;
argv[0].isint = 1;
argv[0].len = 4;
@ -588,16 +559,14 @@ lo_tell64(PGconn *conn, int fd)
PGresult *res;
int result_len;
if (conn == NULL || conn->lobjfuncs == NULL)
{
if (lo_initialize(conn) < 0)
return -1;
}
if (lo_initialize(conn) < 0)
return -1;
if (conn->lobjfuncs->fn_lo_tell64 == 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function lo_tell64\n"));
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function %s\n"),
"lo_tell64");
return -1;
}
@ -632,11 +601,8 @@ lo_unlink(PGconn *conn, Oid lobjId)
int result_len;
int retval;
if (conn == NULL || conn->lobjfuncs == NULL)
{
if (lo_initialize(conn) < 0)
return -1;
}
if (lo_initialize(conn) < 0)
return -1;
argv[0].isint = 1;
argv[0].len = 4;
@ -696,13 +662,19 @@ lo_import_internal(PGconn *conn, const char *filename, Oid oid)
int lobj;
char sebuf[PG_STRERROR_R_BUFLEN];
if (conn == NULL)
return InvalidOid;
/* Since this is the beginning of a query cycle, reset the error buffer */
resetPQExpBuffer(&conn->errorMessage);
/*
* open the file to be read in
*/
fd = open(filename, O_RDONLY | PG_BINARY, 0666);
if (fd < 0)
{ /* error */
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
filename, strerror_r(errno, sebuf, sizeof(sebuf)));
return InvalidOid;
@ -757,6 +729,7 @@ lo_import_internal(PGconn *conn, const char *filename, Oid oid)
(void) lo_close(conn, lobj);
(void) close(fd);
/* deliberately overwrite any error from lo_close */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not read from file \"%s\": %s\n"),
filename,
@ -811,6 +784,7 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename)
int save_errno = errno;
(void) lo_close(conn, lobj);
/* deliberately overwrite any error from lo_close */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open file \"%s\": %s\n"),
filename,
@ -831,6 +805,7 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename)
(void) lo_close(conn, lobj);
(void) close(fd);
/* deliberately overwrite any error from lo_close */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not write to file \"%s\": %s\n"),
filename,
@ -855,7 +830,7 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename)
/* if we already failed, don't overwrite that msg with a close error */
if (close(fd) != 0 && result >= 0)
{
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not write to file \"%s\": %s\n"),
filename, strerror_r(errno, sebuf, sizeof(sebuf)));
result = -1;
@ -868,9 +843,11 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename)
/*
* lo_initialize
*
* Initialize the large object interface for an existing connection.
* We ask the backend about the functions OID's in pg_proc for all
* functions that are required for large object operations.
* Initialize for a new large-object operation on an existing connection.
* Return 0 if OK, -1 on failure.
*
* If we haven't previously done so, we collect the function OIDs from
* pg_proc for all functions that are required for large object operations.
*/
static int
lo_initialize(PGconn *conn)
@ -882,17 +859,26 @@ lo_initialize(PGconn *conn)
const char *fname;
Oid foid;
if (!conn)
/* Nothing we can do with no connection */
if (conn == NULL)
return -1;
/* Since this is the beginning of a query cycle, reset the error buffer */
resetPQExpBuffer(&conn->errorMessage);
/* Nothing else to do if we already collected info */
if (conn->lobjfuncs != NULL)
return 0;
/*
* Allocate the structure to hold the functions OID's
* Allocate the structure to hold the function OIDs. We don't store it
* into the PGconn until it's successfully filled.
*/
lobjfuncs = (PGlobjfuncs *) malloc(sizeof(PGlobjfuncs));
if (lobjfuncs == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return -1;
}
MemSet((char *) lobjfuncs, 0, sizeof(PGlobjfuncs));
@ -942,8 +928,8 @@ lo_initialize(PGconn *conn)
{
free(lobjfuncs);
PQclear(res);
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("query to initialize large object functions did not return data\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("query to initialize large object functions did not return data\n"));
return -1;
}
@ -991,57 +977,65 @@ lo_initialize(PGconn *conn)
*/
if (lobjfuncs->fn_lo_open == 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function lo_open\n"));
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function %s\n"),
"lo_open");
free(lobjfuncs);
return -1;
}
if (lobjfuncs->fn_lo_close == 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function lo_close\n"));
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function %s\n"),
"lo_close");
free(lobjfuncs);
return -1;
}
if (lobjfuncs->fn_lo_creat == 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function lo_creat\n"));
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function %s\n"),
"lo_creat");
free(lobjfuncs);
return -1;
}
if (lobjfuncs->fn_lo_unlink == 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function lo_unlink\n"));
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function %s\n"),
"lo_unlink");
free(lobjfuncs);
return -1;
}
if (lobjfuncs->fn_lo_lseek == 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function lo_lseek\n"));
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function %s\n"),
"lo_lseek");
free(lobjfuncs);
return -1;
}
if (lobjfuncs->fn_lo_tell == 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function lo_tell\n"));
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function %s\n"),
"lo_tell");
free(lobjfuncs);
return -1;
}
if (lobjfuncs->fn_lo_read == 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function loread\n"));
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function %s\n"),
"loread");
free(lobjfuncs);
return -1;
}
if (lobjfuncs->fn_lo_write == 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function lowrite\n"));
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("cannot determine OID of function %s\n"),
"lowrite");
free(lobjfuncs);
return -1;
}

View File

@ -379,8 +379,8 @@ pqCheckOutBufferSpace(size_t bytes_needed, PGconn *conn)
}
/* realloc failed. Probably out of memory */
printfPQExpBuffer(&conn->errorMessage,
"cannot allocate memory for output buffer\n");
appendPQExpBufferStr(&conn->errorMessage,
"cannot allocate memory for output buffer\n");
return EOF;
}
@ -473,8 +473,8 @@ pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
}
/* realloc failed. Probably out of memory */
printfPQExpBuffer(&conn->errorMessage,
"cannot allocate memory for input buffer\n");
appendPQExpBufferStr(&conn->errorMessage,
"cannot allocate memory for input buffer\n");
return EOF;
}
@ -619,8 +619,8 @@ pqReadData(PGconn *conn)
if (conn->sock == PGINVALID_SOCKET)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("connection not open\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("connection not open\n"));
return -1;
}
@ -798,10 +798,10 @@ retry4:
* means the connection has been closed. Cope.
*/
definitelyEOF:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("server closed the connection unexpectedly\n"
"\tThis probably means the server terminated abnormally\n"
"\tbefore or while processing the request.\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("server closed the connection unexpectedly\n"
"\tThis probably means the server terminated abnormally\n"
"\tbefore or while processing the request.\n"));
/* Come here if lower-level code already set a suitable errorMessage */
definitelyFailed:
@ -836,6 +836,7 @@ pqSendSome(PGconn *conn, int len)
{
char *ptr = conn->outBuffer;
int remaining = conn->outCount;
int oldmsglen = conn->errorMessage.len;
int result = 0;
/*
@ -862,13 +863,10 @@ pqSendSome(PGconn *conn, int len)
if (conn->sock == PGINVALID_SOCKET)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("connection not open\n"));
conn->write_failed = true;
/* Transfer error message to conn->write_err_msg, if possible */
/* Insert error message into conn->write_err_msg, if possible */
/* (strdup failure is OK, we'll cope later) */
conn->write_err_msg = strdup(conn->errorMessage.data);
resetPQExpBuffer(&conn->errorMessage);
conn->write_err_msg = strdup(libpq_gettext("connection not open\n"));
/* Discard queued data; no chance it'll ever be sent */
conn->outCount = 0;
return 0;
@ -915,14 +913,16 @@ pqSendSome(PGconn *conn, int len)
* Transfer error message to conn->write_err_msg, if
* possible (strdup failure is OK, we'll cope later).
*
* Note: this assumes that pqsecure_write and its children
* will overwrite not append to conn->errorMessage. If
* that's ever changed, we could remember the length of
* conn->errorMessage at entry to this routine, and then
* save and delete just what was appended.
* We only want to transfer whatever has been appended to
* conn->errorMessage since we entered this routine.
*/
conn->write_err_msg = strdup(conn->errorMessage.data);
resetPQExpBuffer(&conn->errorMessage);
if (!PQExpBufferBroken(&conn->errorMessage))
{
conn->write_err_msg = strdup(conn->errorMessage.data +
oldmsglen);
conn->errorMessage.len = oldmsglen;
conn->errorMessage.data[oldmsglen] = '\0';
}
/* Discard queued data; no chance it'll ever be sent */
conn->outCount = 0;
@ -1056,8 +1056,8 @@ pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
if (result == 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("timeout expired\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("timeout expired\n"));
return 1;
}
@ -1101,8 +1101,8 @@ pqSocketCheck(PGconn *conn, int forRead, int forWrite, time_t end_time)
return -1;
if (conn->sock == PGINVALID_SOCKET)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid socket\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("invalid socket\n"));
return -1;
}
@ -1124,7 +1124,7 @@ pqSocketCheck(PGconn *conn, int forRead, int forWrite, time_t end_time)
{
char sebuf[PG_STRERROR_R_BUFLEN];
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("select() failed: %s\n"),
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
}

View File

@ -83,7 +83,7 @@ pqSetenvPoll(PGconn *conn)
return PGRES_POLLING_OK;
default:
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid setenv state %c, probably indicative of memory corruption\n"),
conn->setenv_state);
goto error_return;
@ -380,7 +380,7 @@ pqSetenvPoll(PGconn *conn)
}
default:
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid state %c, "
"probably indicative of memory corruption\n"),
conn->setenv_state);
@ -493,8 +493,8 @@ pqParseInput2(PGconn *conn)
PGRES_COMMAND_OK);
if (!conn->result)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory"));
pqSaveErrorResult(conn);
}
}
@ -528,8 +528,8 @@ pqParseInput2(PGconn *conn)
PGRES_EMPTY_QUERY);
if (!conn->result)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory"));
pqSaveErrorResult(conn);
}
}
@ -622,7 +622,7 @@ pqParseInput2(PGconn *conn)
* never arrives from the server during protocol 2.0.
*/
default:
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("unexpected response from server; first received character was \"%c\"\n"),
id);
/* build an error result holding the error message */
@ -754,7 +754,7 @@ advance_and_error:
if (!errmsg)
errmsg = libpq_gettext("out of memory for query result");
printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
/*
* XXX: if PQmakeEmptyPGresult() fails, there's probably not much we can
@ -929,7 +929,7 @@ set_error_result:
if (!errmsg)
errmsg = libpq_gettext("out of memory for query result");
printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
/*
* XXX: if PQmakeEmptyPGresult() fails, there's probably not much we can
@ -1042,12 +1042,11 @@ pqGetErrorNotice2(PGconn *conn, bool isError)
{
pqClearAsyncResult(conn); /* redundant, but be safe */
conn->result = res;
resetPQExpBuffer(&conn->errorMessage);
if (res && !PQExpBufferDataBroken(workBuf) && res->errMsg)
appendPQExpBufferStr(&conn->errorMessage, res->errMsg);
else
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory"));
if (conn->xactStatus == PQTRANS_INTRANS)
conn->xactStatus = PQTRANS_INERROR;
}
@ -1203,8 +1202,8 @@ pqGetCopyData2(PGconn *conn, char **buffer, int async)
*buffer = (char *) malloc(msgLength + 1);
if (*buffer == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return -2;
}
memcpy(*buffer, &conn->inBuffer[conn->inStart], msgLength);
@ -1349,8 +1348,8 @@ pqEndcopy2(PGconn *conn)
if (conn->asyncStatus != PGASYNC_COPY_IN &&
conn->asyncStatus != PGASYNC_COPY_OUT)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("no COPY in progress\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("no COPY in progress\n"));
return 1;
}
@ -1367,7 +1366,6 @@ pqEndcopy2(PGconn *conn)
/* Return to active duty */
conn->asyncStatus = PGASYNC_BUSY;
resetPQExpBuffer(&conn->errorMessage);
/* Wait for the completion response */
result = PQgetResult(conn);
@ -1526,7 +1524,7 @@ pqFunctionCall2(PGconn *conn, Oid fnid,
else
{
/* The backend violates the protocol. */
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("protocol error: id=0x%x\n"),
id);
pqSaveErrorResult(conn);
@ -1558,7 +1556,7 @@ pqFunctionCall2(PGconn *conn, Oid fnid,
return PQmakeEmptyPGresult(conn, status);
default:
/* The backend violates the protocol. */
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("protocol error: id=0x%x\n"),
id);
pqSaveErrorResult(conn);

View File

@ -202,8 +202,8 @@ pqParseInput3(PGconn *conn)
PGRES_COMMAND_OK);
if (!conn->result)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory"));
pqSaveErrorResult(conn);
}
}
@ -229,8 +229,8 @@ pqParseInput3(PGconn *conn)
PGRES_EMPTY_QUERY);
if (!conn->result)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory"));
pqSaveErrorResult(conn);
}
}
@ -246,8 +246,8 @@ pqParseInput3(PGconn *conn)
PGRES_COMMAND_OK);
if (!conn->result)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory"));
pqSaveErrorResult(conn);
}
}
@ -326,8 +326,8 @@ pqParseInput3(PGconn *conn)
PGRES_COMMAND_OK);
if (!conn->result)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory"));
pqSaveErrorResult(conn);
}
}
@ -361,8 +361,8 @@ pqParseInput3(PGconn *conn)
else
{
/* Set up to report error at end of query */
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("server sent data (\"D\" message) without prior row description (\"T\" message)\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("server sent data (\"D\" message) without prior row description (\"T\" message)\n"));
pqSaveErrorResult(conn);
/* Discard the unexpected message */
conn->inCursor += msgLength;
@ -404,7 +404,7 @@ pqParseInput3(PGconn *conn)
*/
break;
default:
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("unexpected response from server; first received character was \"%c\"\n"),
id);
/* build an error result holding the error message */
@ -425,7 +425,7 @@ pqParseInput3(PGconn *conn)
else
{
/* Trouble --- report it */
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("message contents do not agree with length in message type \"%c\"\n"),
id);
/* build an error result holding the error message */
@ -445,7 +445,7 @@ pqParseInput3(PGconn *conn)
static void
handleSyncLoss(PGconn *conn, char id, int msgLength)
{
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("lost synchronization with server: got message type \"%c\", length %d\n"),
id, msgLength);
/* build an error result holding the error message */
@ -621,7 +621,7 @@ advance_and_error:
if (!errmsg)
errmsg = libpq_gettext("out of memory for query result");
printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
pqSaveErrorResult(conn);
/*
@ -721,7 +721,7 @@ advance_and_error:
*/
if (!errmsg)
errmsg = libpq_gettext("out of memory");
printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
pqSaveErrorResult(conn);
/*
@ -848,7 +848,7 @@ set_error_result:
if (!errmsg)
errmsg = libpq_gettext("out of memory for query result");
printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
pqSaveErrorResult(conn);
/*
@ -950,8 +950,8 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
pqClearAsyncResult(conn); /* redundant, but be safe */
conn->result = res;
if (PQExpBufferDataBroken(workBuf))
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory"));
else
appendPQExpBufferStr(&conn->errorMessage, workBuf.data);
}
@ -1695,8 +1695,8 @@ pqGetCopyData3(PGconn *conn, char **buffer, int async)
*buffer = (char *) malloc(msgLength + 1);
if (*buffer == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return -2;
}
memcpy(*buffer, &conn->inBuffer[conn->inCursor], msgLength);
@ -1728,8 +1728,8 @@ pqGetline3(PGconn *conn, char *s, int maxlen)
conn->asyncStatus != PGASYNC_COPY_BOTH) ||
conn->copy_is_binary)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("PQgetline: not doing text COPY OUT\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("PQgetline: not doing text COPY OUT\n"));
*s = '\0';
return EOF;
}
@ -1834,8 +1834,8 @@ pqEndcopy3(PGconn *conn)
conn->asyncStatus != PGASYNC_COPY_OUT &&
conn->asyncStatus != PGASYNC_COPY_BOTH)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("no COPY in progress\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("no COPY in progress\n"));
return 1;
}
@ -1868,7 +1868,6 @@ pqEndcopy3(PGconn *conn)
/* Return to active duty */
conn->asyncStatus = PGASYNC_BUSY;
resetPQExpBuffer(&conn->errorMessage);
/*
* Non blocking connections may have to abort at this point. If everyone
@ -2091,7 +2090,7 @@ pqFunctionCall3(PGconn *conn, Oid fnid,
break;
default:
/* The backend violates the protocol. */
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("protocol error: id=0x%x\n"),
id);
pqSaveErrorResult(conn);

View File

@ -94,8 +94,8 @@ pq_verify_peer_name_matches_certificate_name(PGconn *conn,
if (!(host && host[0] != '\0'))
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("host name must be specified\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("host name must be specified\n"));
return -1;
}
@ -106,8 +106,8 @@ pq_verify_peer_name_matches_certificate_name(PGconn *conn,
name = malloc(namelen + 1);
if (name == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return -1;
}
memcpy(name, namedata, namelen);
@ -120,8 +120,8 @@ pq_verify_peer_name_matches_certificate_name(PGconn *conn,
if (namelen != strlen(name))
{
free(name);
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL certificate's name contains embedded null\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("SSL certificate's name contains embedded null\n"));
return -1;
}
@ -167,8 +167,8 @@ pq_verify_peer_name_matches_certificate(PGconn *conn)
/* Check that we have a hostname to compare with. */
if (!(host && host[0] != '\0'))
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("host name must be specified for a verified SSL connection\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("host name must be specified for a verified SSL connection\n"));
return false;
}
@ -184,7 +184,7 @@ pq_verify_peer_name_matches_certificate(PGconn *conn)
*/
if (names_examined > 1)
{
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_ngettext("server certificate for \"%s\" (and %d other name) does not match host name \"%s\"\n",
"server certificate for \"%s\" (and %d other names) does not match host name \"%s\"\n",
names_examined - 1),
@ -192,14 +192,14 @@ pq_verify_peer_name_matches_certificate(PGconn *conn)
}
else if (names_examined == 1)
{
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("server certificate for \"%s\" does not match host name \"%s\"\n"),
first_name, host);
}
else
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get server's host name from server certificate\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("could not get server's host name from server certificate\n"));
}
}

View File

@ -78,7 +78,7 @@
*
* On success, returns the number of data bytes consumed (possibly less than
* len). On failure, returns -1 with errno set appropriately. If the errno
* indicates a non-retryable error, a message is put into conn->errorMessage.
* indicates a non-retryable error, a message is added to conn->errorMessage.
* For retryable errors, caller should call again (passing the same data)
* once the socket is ready.
*/
@ -106,8 +106,8 @@ pg_GSS_write(PGconn *conn, const void *ptr, size_t len)
*/
if (len < PqGSSSendConsumed)
{
printfPQExpBuffer(&conn->errorMessage,
"GSSAPI caller failed to retransmit all data needing to be retried\n");
appendPQExpBufferStr(&conn->errorMessage,
"GSSAPI caller failed to retransmit all data needing to be retried\n");
errno = EINVAL;
return -1;
}
@ -205,15 +205,15 @@ pg_GSS_write(PGconn *conn, const void *ptr, size_t len)
if (conf_state == 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("outgoing GSSAPI message would not use confidentiality\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("outgoing GSSAPI message would not use confidentiality\n"));
errno = EIO; /* for lack of a better idea */
goto cleanup;
}
if (output.length > PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32))
{
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("client tried to send oversize GSSAPI packet (%zu > %zu)\n"),
(size_t) output.length,
PQ_GSS_SEND_BUFFER_SIZE - sizeof(uint32));
@ -258,7 +258,7 @@ cleanup:
*
* Returns the number of data bytes read, or on failure, returns -1
* with errno set appropriately. If the errno indicates a non-retryable
* error, a message is put into conn->errorMessage. For retryable errors,
* error, a message is added to conn->errorMessage. For retryable errors,
* caller should call again once the socket is ready.
*/
ssize_t
@ -350,7 +350,7 @@ pg_GSS_read(PGconn *conn, void *ptr, size_t len)
if (input.length > PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32))
{
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("oversize GSSAPI packet sent by the server (%zu > %zu)\n"),
(size_t) input.length,
PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32));
@ -399,8 +399,8 @@ pg_GSS_read(PGconn *conn, void *ptr, size_t len)
if (conf_state == 0)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("incoming GSSAPI message did not use confidentiality\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("incoming GSSAPI message did not use confidentiality\n"));
ret = -1;
errno = EIO; /* for lack of a better idea */
goto cleanup;
@ -500,8 +500,8 @@ pqsecure_open_gss(PGconn *conn)
PqGSSResultBuffer = malloc(PQ_GSS_RECV_BUFFER_SIZE);
if (!PqGSSSendBuffer || !PqGSSRecvBuffer || !PqGSSResultBuffer)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return PGRES_POLLING_FAILED;
}
PqGSSSendLength = PqGSSSendNext = PqGSSSendConsumed = 0;
@ -578,7 +578,7 @@ pqsecure_open_gss(PGconn *conn)
PqGSSRecvLength += ret;
printfPQExpBuffer(&conn->errorMessage, "%s\n", PqGSSRecvBuffer + 1);
appendPQExpBuffer(&conn->errorMessage, "%s\n", PqGSSRecvBuffer + 1);
return PGRES_POLLING_FAILED;
}
@ -592,7 +592,7 @@ pqsecure_open_gss(PGconn *conn)
input.length = pg_ntoh32(*(uint32 *) PqGSSRecvBuffer);
if (input.length > PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32))
{
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("oversize GSSAPI packet sent by the server (%zu > %zu)\n"),
(size_t) input.length,
PQ_GSS_RECV_BUFFER_SIZE - sizeof(uint32));

View File

@ -181,8 +181,8 @@ rloop:
if (n < 0)
{
/* Not supposed to happen, so we don't translate the msg */
printfPQExpBuffer(&conn->errorMessage,
"SSL_read failed but did not provide error information\n");
appendPQExpBufferStr(&conn->errorMessage,
"SSL_read failed but did not provide error information\n");
/* assume the connection is broken */
result_errno = ECONNRESET;
}
@ -205,20 +205,20 @@ rloop:
result_errno = SOCK_ERRNO;
if (result_errno == EPIPE ||
result_errno == ECONNRESET)
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("server closed the connection unexpectedly\n"
"\tThis probably means the server terminated abnormally\n"
"\tbefore or while processing the request.\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("server closed the connection unexpectedly\n"
"\tThis probably means the server terminated abnormally\n"
"\tbefore or while processing the request.\n"));
else
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: %s\n"),
SOCK_STRERROR(result_errno,
sebuf, sizeof(sebuf)));
}
else
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: EOF detected\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: EOF detected\n"));
/* assume the connection is broken */
result_errno = ECONNRESET;
n = -1;
@ -228,7 +228,7 @@ rloop:
{
char *errm = SSLerrmessage(ecode);
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL error: %s\n"), errm);
SSLerrfree(errm);
/* assume the connection is broken */
@ -243,13 +243,13 @@ rloop:
* a clean connection closure, so we should not report it as a
* server crash.
*/
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL connection has been closed unexpectedly\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("SSL connection has been closed unexpectedly\n"));
result_errno = ECONNRESET;
n = -1;
break;
default:
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("unrecognized SSL error code: %d\n"),
err);
/* assume the connection is broken */
@ -290,8 +290,8 @@ pgtls_write(PGconn *conn, const void *ptr, size_t len)
if (n < 0)
{
/* Not supposed to happen, so we don't translate the msg */
printfPQExpBuffer(&conn->errorMessage,
"SSL_write failed but did not provide error information\n");
appendPQExpBufferStr(&conn->errorMessage,
"SSL_write failed but did not provide error information\n");
/* assume the connection is broken */
result_errno = ECONNRESET;
}
@ -312,20 +312,20 @@ pgtls_write(PGconn *conn, const void *ptr, size_t len)
{
result_errno = SOCK_ERRNO;
if (result_errno == EPIPE || result_errno == ECONNRESET)
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("server closed the connection unexpectedly\n"
"\tThis probably means the server terminated abnormally\n"
"\tbefore or while processing the request.\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("server closed the connection unexpectedly\n"
"\tThis probably means the server terminated abnormally\n"
"\tbefore or while processing the request.\n"));
else
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: %s\n"),
SOCK_STRERROR(result_errno,
sebuf, sizeof(sebuf)));
}
else
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: EOF detected\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: EOF detected\n"));
/* assume the connection is broken */
result_errno = ECONNRESET;
n = -1;
@ -335,7 +335,7 @@ pgtls_write(PGconn *conn, const void *ptr, size_t len)
{
char *errm = SSLerrmessage(ecode);
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL error: %s\n"), errm);
SSLerrfree(errm);
/* assume the connection is broken */
@ -350,13 +350,13 @@ pgtls_write(PGconn *conn, const void *ptr, size_t len)
* a clean connection closure, so we should not report it as a
* server crash.
*/
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL connection has been closed unexpectedly\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("SSL connection has been closed unexpectedly\n"));
result_errno = ECONNRESET;
n = -1;
break;
default:
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("unrecognized SSL error code: %d\n"),
err);
/* assume the connection is broken */
@ -396,8 +396,8 @@ pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len)
if (!OBJ_find_sigid_algs(X509_get_signature_nid(peer_cert),
&algo_nid, NULL))
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not determine server certificate signature algorithm\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("could not determine server certificate signature algorithm\n"));
return NULL;
}
@ -417,7 +417,7 @@ pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len)
algo_type = EVP_get_digestbynid(algo_nid);
if (algo_type == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not find digest for NID %s\n"),
OBJ_nid2sn(algo_nid));
return NULL;
@ -427,8 +427,8 @@ pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len)
if (!X509_digest(peer_cert, algo_type, hash, &hash_size))
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not generate peer certificate hash\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("could not generate peer certificate hash\n"));
return NULL;
}
@ -436,8 +436,8 @@ pgtls_get_peer_certificate_hash(PGconn *conn, size_t *len)
cert_hash = malloc(hash_size);
if (cert_hash == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return NULL;
}
memcpy(cert_hash, hash, hash_size);
@ -484,8 +484,8 @@ openssl_verify_peer_name_matches_certificate_name(PGconn *conn, ASN1_STRING *nam
/* Should not happen... */
if (name_entry == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL certificate's name entry is missing\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("SSL certificate's name entry is missing\n"));
return -1;
}
@ -811,7 +811,7 @@ initialize_SSL(PGconn *conn)
{
char *err = SSLerrmessage(ERR_get_error());
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not create SSL context: %s\n"),
err);
SSLerrfree(err);
@ -850,7 +850,7 @@ initialize_SSL(PGconn *conn)
if (ssl_min_ver == -1)
{
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid value \"%s\" for minimum SSL protocol version\n"),
conn->ssl_min_protocol_version);
SSL_CTX_free(SSL_context);
@ -861,7 +861,7 @@ initialize_SSL(PGconn *conn)
{
char *err = SSLerrmessage(ERR_get_error());
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set minimum SSL protocol version: %s\n"),
err);
SSLerrfree(err);
@ -879,7 +879,7 @@ initialize_SSL(PGconn *conn)
if (ssl_max_ver == -1)
{
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("invalid value \"%s\" for maximum SSL protocol version\n"),
conn->ssl_max_protocol_version);
SSL_CTX_free(SSL_context);
@ -890,7 +890,7 @@ initialize_SSL(PGconn *conn)
{
char *err = SSLerrmessage(ERR_get_error());
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not set maximum SSL protocol version: %s\n"),
err);
SSLerrfree(err);
@ -926,7 +926,7 @@ initialize_SSL(PGconn *conn)
{
char *err = SSLerrmessage(ERR_get_error());
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not read root certificate file \"%s\": %s\n"),
fnbuf, err);
SSLerrfree(err);
@ -970,11 +970,11 @@ initialize_SSL(PGconn *conn)
* that it seems worth having a specialized error message for it.
*/
if (fnbuf[0] == '\0')
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not get home directory to locate root certificate file\n"
"Either provide the file or change sslmode to disable server certificate verification.\n"));
else
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("root certificate file \"%s\" does not exist\n"
"Either provide the file or change sslmode to disable server certificate verification.\n"), fnbuf);
SSL_CTX_free(SSL_context);
@ -1005,7 +1005,7 @@ initialize_SSL(PGconn *conn)
*/
if (errno != ENOENT && errno != ENOTDIR)
{
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not open certificate file \"%s\": %s\n"),
fnbuf, strerror_r(errno, sebuf, sizeof(sebuf)));
SSL_CTX_free(SSL_context);
@ -1024,7 +1024,7 @@ initialize_SSL(PGconn *conn)
{
char *err = SSLerrmessage(ERR_get_error());
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not read certificate file \"%s\": %s\n"),
fnbuf, err);
SSLerrfree(err);
@ -1049,7 +1049,7 @@ initialize_SSL(PGconn *conn)
{
char *err = SSLerrmessage(ERR_get_error());
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not establish SSL connection: %s\n"),
err);
SSLerrfree(err);
@ -1087,8 +1087,8 @@ initialize_SSL(PGconn *conn)
if (engine_str == NULL)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("out of memory\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("out of memory\n"));
return -1;
}
@ -1103,7 +1103,7 @@ initialize_SSL(PGconn *conn)
{
char *err = SSLerrmessage(ERR_get_error());
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not load SSL engine \"%s\": %s\n"),
engine_str, err);
SSLerrfree(err);
@ -1115,7 +1115,7 @@ initialize_SSL(PGconn *conn)
{
char *err = SSLerrmessage(ERR_get_error());
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not initialize SSL engine \"%s\": %s\n"),
engine_str, err);
SSLerrfree(err);
@ -1131,7 +1131,7 @@ initialize_SSL(PGconn *conn)
{
char *err = SSLerrmessage(ERR_get_error());
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not read private SSL key \"%s\" from engine \"%s\": %s\n"),
engine_colon, engine_str, err);
SSLerrfree(err);
@ -1145,7 +1145,7 @@ initialize_SSL(PGconn *conn)
{
char *err = SSLerrmessage(ERR_get_error());
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not load private SSL key \"%s\" from engine \"%s\": %s\n"),
engine_colon, engine_str, err);
SSLerrfree(err);
@ -1182,7 +1182,7 @@ initialize_SSL(PGconn *conn)
if (stat(fnbuf, &buf) != 0)
{
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("certificate present, but not private key file \"%s\"\n"),
fnbuf);
return -1;
@ -1190,7 +1190,7 @@ initialize_SSL(PGconn *conn)
#ifndef WIN32
if (!S_ISREG(buf.st_mode) || buf.st_mode & (S_IRWXG | S_IRWXO))
{
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("private key file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
fnbuf);
return -1;
@ -1215,7 +1215,7 @@ initialize_SSL(PGconn *conn)
*/
if (SSL_use_PrivateKey_file(conn->ssl, fnbuf, SSL_FILETYPE_ASN1) != 1)
{
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not load private key file \"%s\": %s\n"),
fnbuf, err);
SSLerrfree(err);
@ -1233,7 +1233,7 @@ initialize_SSL(PGconn *conn)
{
char *err = SSLerrmessage(ERR_get_error());
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("certificate does not match private key file \"%s\": %s\n"),
fnbuf, err);
SSLerrfree(err);
@ -1287,12 +1287,12 @@ open_client_SSL(PGconn *conn)
char sebuf[PG_STRERROR_R_BUFLEN];
if (r == -1)
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: %s\n"),
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
else
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: EOF detected\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("SSL SYSCALL error: EOF detected\n"));
pgtls_close(conn);
return PGRES_POLLING_FAILED;
}
@ -1300,7 +1300,7 @@ open_client_SSL(PGconn *conn)
{
char *err = SSLerrmessage(ecode);
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("SSL error: %s\n"),
err);
SSLerrfree(err);
@ -1350,7 +1350,7 @@ open_client_SSL(PGconn *conn)
}
default:
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("unrecognized SSL error code: %d\n"),
err);
pgtls_close(conn);
@ -1369,7 +1369,7 @@ open_client_SSL(PGconn *conn)
{
char *err = SSLerrmessage(ERR_get_error());
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("certificate could not be obtained: %s\n"),
err);
SSLerrfree(err);

View File

@ -205,8 +205,8 @@ pqsecure_close(PGconn *conn)
/*
* Read data from a secure connection.
*
* On failure, this function is responsible for putting a suitable message
* into conn->errorMessage. The caller must still inspect errno, but only
* On failure, this function is responsible for appending a suitable message
* to conn->errorMessage. The caller must still inspect errno, but only
* to determine whether to continue/retry after error.
*/
ssize_t
@ -263,14 +263,14 @@ pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
case EPIPE:
case ECONNRESET:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("server closed the connection unexpectedly\n"
"\tThis probably means the server terminated abnormally\n"
"\tbefore or while processing the request.\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("server closed the connection unexpectedly\n"
"\tThis probably means the server terminated abnormally\n"
"\tbefore or while processing the request.\n"));
break;
default:
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not receive data from server: %s\n"),
SOCK_STRERROR(result_errno,
sebuf, sizeof(sebuf)));
@ -287,8 +287,8 @@ pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
/*
* Write data to a secure connection.
*
* On failure, this function is responsible for putting a suitable message
* into conn->errorMessage. The caller must still inspect errno, but only
* On failure, this function is responsible for appending a suitable message
* to conn->errorMessage. The caller must still inspect errno, but only
* to determine whether to continue/retry after error.
*/
ssize_t
@ -376,14 +376,14 @@ retry_masked:
/* FALL THRU */
case ECONNRESET:
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("server closed the connection unexpectedly\n"
"\tThis probably means the server terminated abnormally\n"
"\tbefore or while processing the request.\n"));
appendPQExpBufferStr(&conn->errorMessage,
libpq_gettext("server closed the connection unexpectedly\n"
"\tThis probably means the server terminated abnormally\n"
"\tbefore or while processing the request.\n"));
break;
default:
printfPQExpBuffer(&conn->errorMessage,
appendPQExpBuffer(&conn->errorMessage,
libpq_gettext("could not send data to server: %s\n"),
SOCK_STRERROR(result_errno,
sebuf, sizeof(sebuf)));

View File

@ -522,7 +522,11 @@ struct pg_conn
* connection */
#endif
/* Buffer for current error message */
/*
* Buffer for current error message. This is cleared at the start of any
* connection attempt or query cycle; after that, all code should append
* messages to it, never overwrite.
*/
PQExpBufferData errorMessage; /* expansible string */
/* Buffer for receiving various parts of messages */
@ -600,7 +604,6 @@ extern pgthreadlock_t pg_g_threadlock;
/* === in fe-exec.c === */
extern void pqSetResultError(PGresult *res, const char *msg);
extern void pqCatenateResultError(PGresult *res, const char *msg);
extern void *pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary);
extern char *pqResultStrdup(PGresult *res, const char *str);
extern void pqClearAsyncResult(PGconn *conn);
@ -612,6 +615,7 @@ extern void pqSaveMessageField(PGresult *res, char code,
extern void pqSaveParameterStatus(PGconn *conn, const char *name,
const char *value);
extern int pqRowProcessor(PGconn *conn, const char **errmsgp);
extern int PQsendQueryContinue(PGconn *conn, const char *query);
/* === in fe-protocol2.c === */
@ -708,7 +712,7 @@ extern void pgtls_init_library(bool do_ssl, int do_crypto);
* The conn parameter is only used to be able to pass back an error
* message - no connection-local setup is made here.
*
* Returns 0 if OK, -1 on failure (with a message in conn->errorMessage).
* Returns 0 if OK, -1 on failure (adding a message to conn->errorMessage).
*/
extern int pgtls_init(PGconn *conn);
@ -725,8 +729,8 @@ extern void pgtls_close(PGconn *conn);
/*
* Read data from a secure connection.
*
* On failure, this function is responsible for putting a suitable message
* into conn->errorMessage. The caller must still inspect errno, but only
* On failure, this function is responsible for appending a suitable message
* to conn->errorMessage. The caller must still inspect errno, but only
* to determine whether to continue/retry after error.
*/
extern ssize_t pgtls_read(PGconn *conn, void *ptr, size_t len);
@ -739,8 +743,8 @@ extern bool pgtls_read_pending(PGconn *conn);
/*
* Write data to a secure connection.
*
* On failure, this function is responsible for putting a suitable message
* into conn->errorMessage. The caller must still inspect errno, but only
* On failure, this function is responsible for appending a suitable message
* to conn->errorMessage. The caller must still inspect errno, but only
* to determine whether to continue/retry after error.
*/
extern ssize_t pgtls_write(PGconn *conn, const void *ptr, size_t len);