diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2008-11-26 00:26:23 +0000 | 
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2008-11-26 00:26:23 +0000 | 
| commit | 739259d62e6f96afecea1470c69004631d7aa264 (patch) | |
| tree | e1e9f58dda5d66578f0356bf7593fec8acbaa849 /src/bin/psql/mainloop.c | |
| parent | 8a10096440eaf1f5b918aebec71c2d5ad2687fe6 (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.c | 37 | 
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 */ | 
