From 739259d62e6f96afecea1470c69004631d7aa264 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 26 Nov 2008 00:26:23 +0000 Subject: 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. --- src/bin/psql/mainloop.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) (limited to 'src/bin/psql/mainloop.c') 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 */ -- cgit v1.2.3