diff options
Diffstat (limited to 'src/interfaces/libpq/fe-connect.c')
-rw-r--r-- | src/interfaces/libpq/fe-connect.c | 317 |
1 files changed, 129 insertions, 188 deletions
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index a834ce8cf05..61a1fa6a14a 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -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; } @@ -2027,14 +2033,6 @@ connectDBStart(PGconn *conn) 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 * anything else looks at it.) @@ -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 :-( */ |