]> granicus.if.org Git - postgresql/commitdiff
pgbench: avoid FD_ISSET on an invalid file descriptor
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 15 Feb 2016 23:33:43 +0000 (20:33 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 15 Feb 2016 23:33:43 +0000 (20:33 -0300)
The original code wasn't careful to test the file descriptor returned by
PQsocket() for an invalid socket.  If an invalid socket did turn up,
that would amount to calling FD_ISSET with fd = -1, whereby undefined
behavior can be invoked.

To fix, test file descriptor for validity and stop further processing if
that fails.

Problem noticed by Coverity.

There is an existing FD_ISSET callsite that does check for invalid
sockets beforehand, but the error message reported by it was
strerror(errno); in testing the aforementioned change, that turns out to
result in "bad socket: Success" which isn't terribly helpful.  Instead
use PQerrorMessage() in both places which is more likely to contain an
useful error message.

Backpatch-through: 9.1.

src/bin/pgbench/pgbench.c

index 42a4e6babc1ad11d8936e63afb2b245ef46e012c..596d112d5babdc7f44e7c283cf15756ffd0d2d24 100644 (file)
@@ -3706,7 +3706,7 @@ threadRun(void *arg)
                        sock = PQsocket(st->con);
                        if (sock < 0)
                        {
-                               fprintf(stderr, "bad socket: %s\n", strerror(errno));
+                               fprintf(stderr, "bad socket: %s", PQerrorMessage(st->con));
                                goto done;
                        }
 
@@ -3770,11 +3770,21 @@ threadRun(void *arg)
                        Command   **commands = sql_script[st->use_file].commands;
                        int                     prev_ecnt = st->ecnt;
 
-                       if (st->con && (FD_ISSET(PQsocket(st->con), &input_mask)
-                                                       || commands[st->state]->type == META_COMMAND))
+                       if (st->con)
                        {
-                               if (!doCustom(thread, st, &aggs))
-                                       remains--;      /* I've aborted */
+                               int                     sock = PQsocket(st->con);
+
+                               if (sock < 0)
+                               {
+                                       fprintf(stderr, "bad socket: %s", PQerrorMessage(st->con));
+                                       goto done;
+                               }
+                               if (FD_ISSET(sock, &input_mask) ||
+                                       commands[st->state]->type == META_COMMAND)
+                               {
+                                       if (!doCustom(thread, st, &aggs))
+                                               remains--;              /* I've aborted */
+                               }
                        }
 
                        if (st->ecnt > prev_ecnt && commands[st->state]->type == META_COMMAND)