aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/interfaces/libpq/fe-protocol2.c51
-rw-r--r--src/interfaces/libpq/fe-protocol3.c63
2 files changed, 83 insertions, 31 deletions
diff --git a/src/interfaces/libpq/fe-protocol2.c b/src/interfaces/libpq/fe-protocol2.c
index 59e4a4973f2..addbd28c5b0 100644
--- a/src/interfaces/libpq/fe-protocol2.c
+++ b/src/interfaces/libpq/fe-protocol2.c
@@ -498,10 +498,17 @@ pqParseInput2(PGconn *conn)
conn->result = PQmakeEmptyPGresult(conn,
PGRES_COMMAND_OK);
if (!conn->result)
- return;
+ {
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("out of memory"));
+ pqSaveErrorResult(conn);
+ }
+ }
+ if (conn->result)
+ {
+ strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
+ CMDSTATUS_LEN);
}
- strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
- CMDSTATUS_LEN);
checkXactStatus(conn, conn->workBuffer.data);
conn->asyncStatus = PGASYNC_READY;
break;
@@ -522,8 +529,16 @@ pqParseInput2(PGconn *conn)
"unexpected character %c following empty query response (\"I\" message)",
id);
if (conn->result == NULL)
+ {
conn->result = PQmakeEmptyPGresult(conn,
PGRES_EMPTY_QUERY);
+ if (!conn->result)
+ {
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("out of memory"));
+ pqSaveErrorResult(conn);
+ }
+ }
conn->asyncStatus = PGASYNC_READY;
break;
case 'K': /* secret key data from the backend */
@@ -965,14 +980,17 @@ pqGetErrorNotice2(PGconn *conn, bool isError)
* Make a PGresult to hold the message. We temporarily lie about the
* result status, so that PQmakeEmptyPGresult doesn't uselessly copy
* conn->errorMessage.
+ *
+ * NB: This allocation can fail, if you run out of memory. The rest of the
+ * function handles that gracefully, and we still try to set the error
+ * message as the connection's error message.
*/
res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY);
- if (!res)
- goto failure;
- res->resultStatus = isError ? PGRES_FATAL_ERROR : PGRES_NONFATAL_ERROR;
- res->errMsg = pqResultStrdup(res, workBuf.data);
- if (!res->errMsg)
- goto failure;
+ if (res)
+ {
+ res->resultStatus = isError ? PGRES_FATAL_ERROR : PGRES_NONFATAL_ERROR;
+ res->errMsg = pqResultStrdup(res, workBuf.data);
+ }
/*
* Break the message into fields. We can't do very much here, but we can
@@ -1024,15 +1042,22 @@ pqGetErrorNotice2(PGconn *conn, bool isError)
pqClearAsyncResult(conn);
conn->result = res;
resetPQExpBuffer(&conn->errorMessage);
- appendPQExpBufferStr(&conn->errorMessage, res->errMsg);
+ if (res && !PQExpBufferDataBroken(workBuf) && res->errMsg)
+ appendPQExpBufferStr(&conn->errorMessage, res->errMsg);
+ else
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("out of memory"));
if (conn->xactStatus == PQTRANS_INTRANS)
conn->xactStatus = PQTRANS_INERROR;
}
else
{
- if (res->noticeHooks.noticeRec != NULL)
- (*res->noticeHooks.noticeRec) (res->noticeHooks.noticeRecArg, res);
- PQclear(res);
+ if (res)
+ {
+ if (res->noticeHooks.noticeRec != NULL)
+ (*res->noticeHooks.noticeRec) (res->noticeHooks.noticeRecArg, res);
+ PQclear(res);
+ }
}
termPQExpBuffer(&workBuf);
diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c
index c514ca5841c..cccc731d009 100644
--- a/src/interfaces/libpq/fe-protocol3.c
+++ b/src/interfaces/libpq/fe-protocol3.c
@@ -204,10 +204,15 @@ pqParseInput3(PGconn *conn)
conn->result = PQmakeEmptyPGresult(conn,
PGRES_COMMAND_OK);
if (!conn->result)
- return;
+ {
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("out of memory"));
+ pqSaveErrorResult(conn);
+ }
}
- strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
- CMDSTATUS_LEN);
+ if (conn->result)
+ strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
+ CMDSTATUS_LEN);
conn->asyncStatus = PGASYNC_READY;
break;
case 'E': /* error return */
@@ -226,7 +231,11 @@ pqParseInput3(PGconn *conn)
conn->result = PQmakeEmptyPGresult(conn,
PGRES_EMPTY_QUERY);
if (!conn->result)
- return;
+ {
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("out of memory"));
+ pqSaveErrorResult(conn);
+ }
}
conn->asyncStatus = PGASYNC_READY;
break;
@@ -239,7 +248,11 @@ pqParseInput3(PGconn *conn)
conn->result = PQmakeEmptyPGresult(conn,
PGRES_COMMAND_OK);
if (!conn->result)
- return;
+ {
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("out of memory"));
+ pqSaveErrorResult(conn);
+ }
}
conn->asyncStatus = PGASYNC_READY;
}
@@ -306,7 +319,11 @@ pqParseInput3(PGconn *conn)
conn->result = PQmakeEmptyPGresult(conn,
PGRES_COMMAND_OK);
if (!conn->result)
- return;
+ {
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("out of memory"));
+ pqSaveErrorResult(conn);
+ }
}
conn->asyncStatus = PGASYNC_READY;
}
@@ -822,11 +839,14 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
* Make a PGresult to hold the accumulated fields. We temporarily lie
* about the result status, so that PQmakeEmptyPGresult doesn't uselessly
* copy conn->errorMessage.
+ *
+ * NB: This allocation can fail, if you run out of memory. The rest of the
+ * function handles that gracefully, and we still try to set the error
+ * message as the connection's error message.
*/
res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY);
- if (!res)
- goto fail;
- res->resultStatus = isError ? PGRES_FATAL_ERROR : PGRES_NONFATAL_ERROR;
+ if (res)
+ res->resultStatus = isError ? PGRES_FATAL_ERROR : PGRES_NONFATAL_ERROR;
/*
* Read the fields and save into res.
@@ -966,20 +986,27 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
*/
if (isError)
{
- res->errMsg = pqResultStrdup(res, workBuf.data);
- if (!res->errMsg)
- goto fail;
+ if (res)
+ res->errMsg = pqResultStrdup(res, workBuf.data);
pqClearAsyncResult(conn);
conn->result = res;
- appendPQExpBufferStr(&conn->errorMessage, workBuf.data);
+ if (PQExpBufferDataBroken(workBuf))
+ printfPQExpBuffer(&conn->errorMessage,
+ libpq_gettext("out of memory"));
+ else
+ appendPQExpBufferStr(&conn->errorMessage, workBuf.data);
}
else
{
- /* We can cheat a little here and not copy the message. */
- res->errMsg = workBuf.data;
- if (res->noticeHooks.noticeRec != NULL)
- (*res->noticeHooks.noticeRec) (res->noticeHooks.noticeRecArg, res);
- PQclear(res);
+ /* if we couldn't allocate the result set, just discard the NOTICE */
+ if (res)
+ {
+ /* We can cheat a little here and not copy the message. */
+ res->errMsg = workBuf.data;
+ if (res->noticeHooks.noticeRec != NULL)
+ (*res->noticeHooks.noticeRec) (res->noticeHooks.noticeRecArg, res);
+ PQclear(res);
+ }
}
termPQExpBuffer(&workBuf);