Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit514b4c1

Browse files
committed
Improve libpq's handling of OOM during error message construction.
Commitffa2e46 changed libpq so that multiple error reportsoccurring during one operation (a connection attempt or query)are accumulated in conn->errorMessage, where before new onesusually replaced any prior error. At least in theory, that makesus more vulnerable to running out of memory for the errorMessagebuffer. If it did happen, the user would be left with just anempty-string error report, which is pretty unhelpful.We can improve this by relying on pqexpbuffer.c's existing "brokenbuffer" convention to track whether we've hit OOM for the currentoperation's error string, and then substituting a constant "out ofmemory" string in the small number of places where the errorMessageis read out.While at it, apply the same method to similar OOM cases inpqInternalNotice and pqGetErrorNotice3.Back-patch to v14 whereffa2e46 came in. In principle this couldgo back further; but in view of the lack of field reports, thehazard seems negligible in older branches.Discussion:https://postgr.es/m/530153.1627425648@sss.pgh.pa.us
1 parentb35a67b commit514b4c1

File tree

4 files changed

+48
-19
lines changed

4 files changed

+48
-19
lines changed

‎src/interfaces/libpq/fe-connect.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6739,6 +6739,14 @@ PQerrorMessage(const PGconn *conn)
67396739
if (!conn)
67406740
returnlibpq_gettext("connection pointer is NULL\n");
67416741

6742+
/*
6743+
* The errorMessage buffer might be marked "broken" due to having
6744+
* previously failed to allocate enough memory for the message. In that
6745+
* case, tell the application we ran out of memory.
6746+
*/
6747+
if (PQExpBufferBroken(&conn->errorMessage))
6748+
returnlibpq_gettext("out of memory\n");
6749+
67426750
returnconn->errorMessage.data;
67436751
}
67446752

‎src/interfaces/libpq/fe-exec.c

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
191191
/* non-error cases */
192192
break;
193193
default:
194-
pqSetResultError(result,conn->errorMessage.data);
194+
pqSetResultError(result,&conn->errorMessage);
195195
break;
196196
}
197197

@@ -662,14 +662,28 @@ pqResultStrdup(PGresult *res, const char *str)
662662
*assign a new error message to a PGresult
663663
*/
664664
void
665-
pqSetResultError(PGresult*res,constchar*msg)
665+
pqSetResultError(PGresult*res,PQExpBuffererrorMessage)
666666
{
667+
char*msg;
668+
667669
if (!res)
668670
return;
669-
if (msg&&*msg)
670-
res->errMsg=pqResultStrdup(res,msg);
671+
672+
/*
673+
* We handle two OOM scenarios here. The errorMessage buffer might be
674+
* marked "broken" due to having previously failed to allocate enough
675+
* memory for the message, or it might be fine but pqResultStrdup fails
676+
* and returns NULL. In either case, just make res->errMsg point directly
677+
* at a constant "out of memory" string.
678+
*/
679+
if (!PQExpBufferBroken(errorMessage))
680+
msg=pqResultStrdup(res,errorMessage->data);
681+
else
682+
msg=NULL;
683+
if (msg)
684+
res->errMsg=msg;
671685
else
672-
res->errMsg=NULL;
686+
res->errMsg=libpq_gettext("out of memory\n");
673687
}
674688

675689
/*
@@ -852,19 +866,19 @@ pqInternalNotice(const PGNoticeHooks *hooks, const char *fmt,...)
852866
/* XXX should provide a SQLSTATE too? */
853867

854868
/*
855-
* Result text is always just the primary message + newline. If we can't
856-
* allocate it,don't bother invoking the receiver.
869+
* Result text is always just the primary message + newline.If we can't
870+
* allocate it,substitute "out of memory", as in pqSetResultError.
857871
*/
858872
res->errMsg= (char*)pqResultAlloc(res,strlen(msgBuf)+2, false);
859873
if (res->errMsg)
860-
{
861874
sprintf(res->errMsg,"%s\n",msgBuf);
875+
else
876+
res->errMsg=libpq_gettext("out of memory\n");
862877

863-
/*
864-
* Pass to receiver, then free it.
865-
*/
866-
res->noticeHooks.noticeRec(res->noticeHooks.noticeRecArg,res);
867-
}
878+
/*
879+
* Pass to receiver, then free it.
880+
*/
881+
res->noticeHooks.noticeRec(res->noticeHooks.noticeRecArg,res);
868882
PQclear(res);
869883
}
870884

@@ -2122,7 +2136,7 @@ PQgetResult(PGconn *conn)
21222136
appendPQExpBuffer(&conn->errorMessage,
21232137
libpq_gettext("PGEventProc \"%s\" failed during PGEVT_RESULTCREATE event\n"),
21242138
res->events[i].name);
2125-
pqSetResultError(res,conn->errorMessage.data);
2139+
pqSetResultError(res,&conn->errorMessage);
21262140
res->resultStatus=PGRES_FATAL_ERROR;
21272141
break;
21282142
}

‎src/interfaces/libpq/fe-protocol3.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -967,12 +967,12 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
967967
if (isError)
968968
{
969969
if (res)
970-
res->errMsg=pqResultStrdup(res,workBuf.data);
970+
pqSetResultError(res,&workBuf);
971971
pqClearAsyncResult(conn);/* redundant, but be safe */
972972
conn->result=res;
973973
if (PQExpBufferDataBroken(workBuf))
974974
appendPQExpBufferStr(&conn->errorMessage,
975-
libpq_gettext("out of memory"));
975+
libpq_gettext("out of memory\n"));
976976
else
977977
appendPQExpBufferStr(&conn->errorMessage,workBuf.data);
978978
}
@@ -981,8 +981,15 @@ pqGetErrorNotice3(PGconn *conn, bool isError)
981981
/* if we couldn't allocate the result set, just discard the NOTICE */
982982
if (res)
983983
{
984-
/* We can cheat a little here and not copy the message. */
985-
res->errMsg=workBuf.data;
984+
/*
985+
* We can cheat a little here and not copy the message. But if we
986+
* were unlucky enough to run out of memory while filling workBuf,
987+
* insert "out of memory", as in pqSetResultError.
988+
*/
989+
if (PQExpBufferDataBroken(workBuf))
990+
res->errMsg=libpq_gettext("out of memory\n");
991+
else
992+
res->errMsg=workBuf.data;
986993
if (res->noticeHooks.noticeRec!=NULL)
987994
res->noticeHooks.noticeRec(res->noticeHooks.noticeRecArg,res);
988995
PQclear(res);

‎src/interfaces/libpq/libpq-int.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ extern pgthreadlock_t pg_g_threadlock;
637637

638638
/* === in fe-exec.c === */
639639

640-
externvoidpqSetResultError(PGresult*res,constchar*msg);
640+
externvoidpqSetResultError(PGresult*res,PQExpBuffererrorMessage);
641641
externvoid*pqResultAlloc(PGresult*res,size_tnBytes,boolisBinary);
642642
externchar*pqResultStrdup(PGresult*res,constchar*str);
643643
externvoidpqClearAsyncResult(PGconn*conn);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp