summaryrefslogtreecommitdiff
path: root/src/bin/psql/mainloop.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2008-11-26 00:26:23 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2008-11-26 00:26:23 +0000
commit739259d62e6f96afecea1470c69004631d7aa264 (patch)
treee1e9f58dda5d66578f0356bf7593fec8acbaa849 /src/bin/psql/mainloop.c
parent8a10096440eaf1f5b918aebec71c2d5ad2687fe6 (diff)
Adjust the behavior of the PQExpBuffer code to make it have well-defined
results (ie, an empty "broken" buffer) if memory overrun occurs anywhere along the way to filling the buffer. The previous coding would just silently discard portions of the intended buffer contents, as exhibited in trouble report from Sam Mason. Also, tweak psql's main loop to correctly detect and report such overruns. There's probably much more that should be done in this line, but this is a start.
Diffstat (limited to 'src/bin/psql/mainloop.c')
-rw-r--r--src/bin/psql/mainloop.c37
1 files changed, 28 insertions, 9 deletions
diff --git a/src/bin/psql/mainloop.c b/src/bin/psql/mainloop.c
index 526674c8181..16532e2d420 100644
--- a/src/bin/psql/mainloop.c
+++ b/src/bin/psql/mainloop.c
@@ -3,7 +3,7 @@
*
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/bin/psql/mainloop.c,v 1.92 2008/06/10 20:58:19 neilc Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/mainloop.c,v 1.93 2008/11/26 00:26:23 tgl Exp $
*/
#include "postgres_fe.h"
#include "mainloop.h"
@@ -26,9 +26,9 @@ int
MainLoop(FILE *source)
{
PsqlScanState scan_state; /* lexer working state */
- PQExpBuffer query_buf; /* buffer for query being accumulated */
- PQExpBuffer previous_buf; /* if there isn't anything in the new buffer
- * yet, use this one for \e, etc. */
+ volatile PQExpBuffer query_buf; /* buffer for query being accumulated */
+ volatile PQExpBuffer previous_buf; /* if there isn't anything in the new
+ * buffer yet, use this one for \e, etc. */
PQExpBuffer history_buf; /* earlier lines of a multi-line command, not
* yet saved to readline history */
char *line; /* current line of input */
@@ -62,7 +62,9 @@ MainLoop(FILE *source)
query_buf = createPQExpBuffer();
previous_buf = createPQExpBuffer();
history_buf = createPQExpBuffer();
- if (!query_buf || !previous_buf || !history_buf)
+ if (PQExpBufferBroken(query_buf) ||
+ PQExpBufferBroken(previous_buf) ||
+ PQExpBufferBroken(history_buf))
{
psql_error("out of memory\n");
exit(EXIT_FAILURE);
@@ -220,6 +222,12 @@ MainLoop(FILE *source)
scan_result = psql_scan(scan_state, query_buf, &prompt_tmp);
prompt_status = prompt_tmp;
+ if (PQExpBufferBroken(query_buf))
+ {
+ psql_error("out of memory\n");
+ exit(EXIT_FAILURE);
+ }
+
/*
* Send command if semicolon found, or if end of line and we're in
* single-line mode.
@@ -242,9 +250,15 @@ MainLoop(FILE *source)
success = SendQuery(query_buf->data);
slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR;
- resetPQExpBuffer(previous_buf);
- appendPQExpBufferStr(previous_buf, query_buf->data);
+ /* transfer query to previous_buf by pointer-swapping */
+ {
+ PQExpBuffer swap_buf = previous_buf;
+
+ previous_buf = query_buf;
+ query_buf = swap_buf;
+ }
resetPQExpBuffer(query_buf);
+
added_nl_pos = -1;
/* we need not do psql_scan_reset() here */
}
@@ -294,8 +308,13 @@ MainLoop(FILE *source)
{
success = SendQuery(query_buf->data);
- resetPQExpBuffer(previous_buf);
- appendPQExpBufferStr(previous_buf, query_buf->data);
+ /* transfer query to previous_buf by pointer-swapping */
+ {
+ PQExpBuffer swap_buf = previous_buf;
+
+ previous_buf = query_buf;
+ query_buf = swap_buf;
+ }
resetPQExpBuffer(query_buf);
/* flush any paren nesting info after forced send */