aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2022-01-17 12:52:44 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2022-01-17 12:52:44 -0500
commit050949877004f003b7d95fddf8f572a32f3a2f70 (patch)
tree72cc73169580e5ca70f48ec88829f01f5dbeb80e
parent17da9d4c28297fd699cbbda969a9f64c4c09c665 (diff)
downloadpostgresql-050949877004f003b7d95fddf8f572a32f3a2f70.tar.gz
postgresql-050949877004f003b7d95fddf8f572a32f3a2f70.zip
Avoid calling strerror[_r] in PQcancel().
PQcancel() is supposed to be safe to call from a signal handler, and indeed psql uses it that way. All of the library functions it uses are specified to be async-signal-safe by POSIX ... except for strerror. Neither plain strerror nor strerror_r are considered safe. When this code was written, back in the dark ages, we probably figured "oh, strerror will just index into a constant array of strings" ... but in any locale except C, that's unlikely to be true. Probably the reason we've not heard complaints is that (a) this error-handling code is unlikely to be reached in normal use, and (b) in many scenarios, localized error strings would already have been loaded, after which maybe it's safe to call strerror here. Still, this is clearly unacceptable. The best we can do without relying on strerror is to print the decimal value of errno, so make it do that instead. (This is probably not much loss of user-friendliness, given that it is hard to get a failure here.) Back-patch to all supported branches. Discussion: https://postgr.es/m/2937814.1641960929@sss.pgh.pa.us
-rw-r--r--src/interfaces/libpq/fe-connect.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index d6e38d89fab..133b7617bb7 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -4435,7 +4435,6 @@ internal_cancel(SockAddr *raddr, int be_pid, int be_key,
{
int save_errno = SOCK_ERRNO;
pgsocket tmpsock = PGINVALID_SOCKET;
- char sebuf[PG_STRERROR_R_BUFLEN];
int maxlen;
struct
{
@@ -4514,8 +4513,25 @@ cancel_errReturn:
maxlen = errbufsize - strlen(errbuf) - 2;
if (maxlen >= 0)
{
- strncat(errbuf, SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)),
- maxlen);
+ /*
+ * We can't invoke strerror here, since it's not signal-safe. Settle
+ * for printing the decimal value of errno. Even that has to be done
+ * the hard way.
+ */
+ int val = SOCK_ERRNO;
+ char buf[32];
+ char *bufp;
+
+ bufp = buf + sizeof(buf) - 1;
+ *bufp = '\0';
+ do
+ {
+ *(--bufp) = (val % 10) + '0';
+ val /= 10;
+ } while (val > 0);
+ bufp -= 6;
+ memcpy(bufp, "error ", 6);
+ strncat(errbuf, bufp, maxlen);
strcat(errbuf, "\n");
}
if (tmpsock != PGINVALID_SOCKET)