1 /*-------------------------------------------------------------------------
2  *
3  * fe-protocol3.c
4  *	  functions that are specific to frontend/backend protocol version 3
5  *
6  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *	  src/interfaces/libpq/fe-protocol3.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres_fe.h"
16 
17 #include <ctype.h>
18 #include <fcntl.h>
19 
20 #ifdef WIN32
21 #include "win32.h"
22 #else
23 #include <unistd.h>
24 #ifdef HAVE_NETINET_TCP_H
25 #include <netinet/tcp.h>
26 #endif
27 #endif
28 
29 #include "libpq-fe.h"
30 #include "libpq-int.h"
31 #include "mb/pg_wchar.h"
32 #include "port/pg_bswap.h"
33 
34 /*
35  * This macro lists the backend message types that could be "long" (more
36  * than a couple of kilobytes).
37  */
38 #define VALID_LONG_MESSAGE_TYPE(id) \
39 	((id) == 'T' || (id) == 'D' || (id) == 'd' || (id) == 'V' || \
40 	 (id) == 'E' || (id) == 'N' || (id) == 'A')
41 
42 
43 static void handleSyncLoss(PGconn *conn, char id, int msgLength);
44 static int	getRowDescriptions(PGconn *conn, int msgLength);
45 static int	getParamDescriptions(PGconn *conn, int msgLength);
46 static int	getAnotherTuple(PGconn *conn, int msgLength);
47 static int	getParameterStatus(PGconn *conn);
48 static int	getNotify(PGconn *conn);
49 static int	getCopyStart(PGconn *conn, ExecStatusType copytype);
50 static int	getReadyForQuery(PGconn *conn);
51 static void reportErrorPosition(PQExpBuffer msg, const char *query,
52 								int loc, int encoding);
53 static int	build_startup_packet(const PGconn *conn, char *packet,
54 								 const PQEnvironmentOption *options);
55 
56 
57 /*
58  * parseInput: if appropriate, parse input data from backend
59  * until input is exhausted or a stopping state is reached.
60  * Note that this function will NOT attempt to read more data from the backend.
61  */
62 void
pqParseInput3(PGconn * conn)63 pqParseInput3(PGconn *conn)
64 {
65 	char		id;
66 	int			msgLength;
67 	int			avail;
68 
69 	/*
70 	 * Loop to parse successive complete messages available in the buffer.
71 	 */
72 	for (;;)
73 	{
74 		/*
75 		 * Try to read a message.  First get the type code and length. Return
76 		 * if not enough data.
77 		 */
78 		conn->inCursor = conn->inStart;
79 		if (pqGetc(&id, conn))
80 			return;
81 		if (pqGetInt(&msgLength, 4, conn))
82 			return;
83 
84 		/*
85 		 * Try to validate message type/length here.  A length less than 4 is
86 		 * definitely broken.  Large lengths should only be believed for a few
87 		 * message types.
88 		 */
89 		if (msgLength < 4)
90 		{
91 			handleSyncLoss(conn, id, msgLength);
92 			return;
93 		}
94 		if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
95 		{
96 			handleSyncLoss(conn, id, msgLength);
97 			return;
98 		}
99 
100 		/*
101 		 * Can't process if message body isn't all here yet.
102 		 */
103 		msgLength -= 4;
104 		avail = conn->inEnd - conn->inCursor;
105 		if (avail < msgLength)
106 		{
107 			/*
108 			 * Before returning, enlarge the input buffer if needed to hold
109 			 * the whole message.  This is better than leaving it to
110 			 * pqReadData because we can avoid multiple cycles of realloc()
111 			 * when the message is large; also, we can implement a reasonable
112 			 * recovery strategy if we are unable to make the buffer big
113 			 * enough.
114 			 */
115 			if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
116 									 conn))
117 			{
118 				/*
119 				 * XXX add some better recovery code... plan is to skip over
120 				 * the message using its length, then report an error. For the
121 				 * moment, just treat this like loss of sync (which indeed it
122 				 * might be!)
123 				 */
124 				handleSyncLoss(conn, id, msgLength);
125 			}
126 			return;
127 		}
128 
129 		/*
130 		 * NOTIFY and NOTICE messages can happen in any state; always process
131 		 * them right away.
132 		 *
133 		 * Most other messages should only be processed while in BUSY state.
134 		 * (In particular, in READY state we hold off further parsing until
135 		 * the application collects the current PGresult.)
136 		 *
137 		 * However, if the state is IDLE then we got trouble; we need to deal
138 		 * with the unexpected message somehow.
139 		 *
140 		 * ParameterStatus ('S') messages are a special case: in IDLE state we
141 		 * must process 'em (this case could happen if a new value was adopted
142 		 * from config file due to SIGHUP), but otherwise we hold off until
143 		 * BUSY state.
144 		 */
145 		if (id == 'A')
146 		{
147 			if (getNotify(conn))
148 				return;
149 		}
150 		else if (id == 'N')
151 		{
152 			if (pqGetErrorNotice3(conn, false))
153 				return;
154 		}
155 		else if (conn->asyncStatus != PGASYNC_BUSY)
156 		{
157 			/* If not IDLE state, just wait ... */
158 			if (conn->asyncStatus != PGASYNC_IDLE)
159 				return;
160 
161 			/*
162 			 * We're also notionally not-IDLE when in pipeline mode the state
163 			 * says "idle" (so we have completed receiving the results of one
164 			 * query from the server and dispatched them to the application)
165 			 * but another query is queued; yield back control to caller so
166 			 * that they can initiate processing of the next query in the
167 			 * queue.
168 			 */
169 			if (conn->pipelineStatus != PQ_PIPELINE_OFF &&
170 				conn->cmd_queue_head != NULL)
171 				return;
172 
173 			/*
174 			 * Unexpected message in IDLE state; need to recover somehow.
175 			 * ERROR messages are handled using the notice processor;
176 			 * ParameterStatus is handled normally; anything else is just
177 			 * dropped on the floor after displaying a suitable warning
178 			 * notice.  (An ERROR is very possibly the backend telling us why
179 			 * it is about to close the connection, so we don't want to just
180 			 * discard it...)
181 			 */
182 			if (id == 'E')
183 			{
184 				if (pqGetErrorNotice3(conn, false /* treat as notice */ ))
185 					return;
186 			}
187 			else if (id == 'S')
188 			{
189 				if (getParameterStatus(conn))
190 					return;
191 			}
192 			else
193 			{
194 				/* Any other case is unexpected and we summarily skip it */
195 				pqInternalNotice(&conn->noticeHooks,
196 								 "message type 0x%02x arrived from server while idle",
197 								 id);
198 				/* Discard the unexpected message */
199 				conn->inCursor += msgLength;
200 			}
201 		}
202 		else
203 		{
204 			/*
205 			 * In BUSY state, we can process everything.
206 			 */
207 			switch (id)
208 			{
209 				case 'C':		/* command complete */
210 					if (pqGets(&conn->workBuffer, conn))
211 						return;
212 					if (conn->result == NULL)
213 					{
214 						conn->result = PQmakeEmptyPGresult(conn,
215 														   PGRES_COMMAND_OK);
216 						if (!conn->result)
217 						{
218 							appendPQExpBufferStr(&conn->errorMessage,
219 												 libpq_gettext("out of memory"));
220 							pqSaveErrorResult(conn);
221 						}
222 					}
223 					if (conn->result)
224 						strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
225 								CMDSTATUS_LEN);
226 					conn->asyncStatus = PGASYNC_READY;
227 					break;
228 				case 'E':		/* error return */
229 					if (pqGetErrorNotice3(conn, true))
230 						return;
231 					conn->asyncStatus = PGASYNC_READY;
232 					break;
233 				case 'Z':		/* sync response, backend is ready for new
234 								 * query */
235 					if (getReadyForQuery(conn))
236 						return;
237 					if (conn->pipelineStatus != PQ_PIPELINE_OFF)
238 					{
239 						conn->result = PQmakeEmptyPGresult(conn,
240 														   PGRES_PIPELINE_SYNC);
241 						if (!conn->result)
242 						{
243 							appendPQExpBufferStr(&conn->errorMessage,
244 												 libpq_gettext("out of memory"));
245 							pqSaveErrorResult(conn);
246 						}
247 						else
248 						{
249 							conn->pipelineStatus = PQ_PIPELINE_ON;
250 							conn->asyncStatus = PGASYNC_READY;
251 						}
252 					}
253 					else
254 					{
255 						/*
256 						 * In simple query protocol, advance the command queue
257 						 * (see PQgetResult).
258 						 */
259 						if (conn->cmd_queue_head &&
260 							conn->cmd_queue_head->queryclass == PGQUERY_SIMPLE)
261 							pqCommandQueueAdvance(conn);
262 						conn->asyncStatus = PGASYNC_IDLE;
263 					}
264 					break;
265 				case 'I':		/* empty query */
266 					if (conn->result == NULL)
267 					{
268 						conn->result = PQmakeEmptyPGresult(conn,
269 														   PGRES_EMPTY_QUERY);
270 						if (!conn->result)
271 						{
272 							appendPQExpBufferStr(&conn->errorMessage,
273 												 libpq_gettext("out of memory"));
274 							pqSaveErrorResult(conn);
275 						}
276 					}
277 					conn->asyncStatus = PGASYNC_READY;
278 					break;
279 				case '1':		/* Parse Complete */
280 					/* If we're doing PQprepare, we're done; else ignore */
281 					if (conn->cmd_queue_head &&
282 						conn->cmd_queue_head->queryclass == PGQUERY_PREPARE)
283 					{
284 						if (conn->result == NULL)
285 						{
286 							conn->result = PQmakeEmptyPGresult(conn,
287 															   PGRES_COMMAND_OK);
288 							if (!conn->result)
289 							{
290 								appendPQExpBufferStr(&conn->errorMessage,
291 													 libpq_gettext("out of memory"));
292 								pqSaveErrorResult(conn);
293 							}
294 						}
295 						conn->asyncStatus = PGASYNC_READY;
296 					}
297 					break;
298 				case '2':		/* Bind Complete */
299 				case '3':		/* Close Complete */
300 					/* Nothing to do for these message types */
301 					break;
302 				case 'S':		/* parameter status */
303 					if (getParameterStatus(conn))
304 						return;
305 					break;
306 				case 'K':		/* secret key data from the backend */
307 
308 					/*
309 					 * This is expected only during backend startup, but it's
310 					 * just as easy to handle it as part of the main loop.
311 					 * Save the data and continue processing.
312 					 */
313 					if (pqGetInt(&(conn->be_pid), 4, conn))
314 						return;
315 					if (pqGetInt(&(conn->be_key), 4, conn))
316 						return;
317 					break;
318 				case 'T':		/* Row Description */
319 					if (conn->result != NULL &&
320 						conn->result->resultStatus == PGRES_FATAL_ERROR)
321 					{
322 						/*
323 						 * We've already choked for some reason.  Just discard
324 						 * the data till we get to the end of the query.
325 						 */
326 						conn->inCursor += msgLength;
327 					}
328 					else if (conn->result == NULL ||
329 							 (conn->cmd_queue_head &&
330 							  conn->cmd_queue_head->queryclass == PGQUERY_DESCRIBE))
331 					{
332 						/* First 'T' in a query sequence */
333 						if (getRowDescriptions(conn, msgLength))
334 							return;
335 					}
336 					else
337 					{
338 						/*
339 						 * A new 'T' message is treated as the start of
340 						 * another PGresult.  (It is not clear that this is
341 						 * really possible with the current backend.) We stop
342 						 * parsing until the application accepts the current
343 						 * result.
344 						 */
345 						conn->asyncStatus = PGASYNC_READY;
346 						return;
347 					}
348 					break;
349 				case 'n':		/* No Data */
350 
351 					/*
352 					 * NoData indicates that we will not be seeing a
353 					 * RowDescription message because the statement or portal
354 					 * inquired about doesn't return rows.
355 					 *
356 					 * If we're doing a Describe, we have to pass something
357 					 * back to the client, so set up a COMMAND_OK result,
358 					 * instead of PGRES_TUPLES_OK.  Otherwise we can just
359 					 * ignore this message.
360 					 */
361 					if (conn->cmd_queue_head &&
362 						conn->cmd_queue_head->queryclass == PGQUERY_DESCRIBE)
363 					{
364 						if (conn->result == NULL)
365 						{
366 							conn->result = PQmakeEmptyPGresult(conn,
367 															   PGRES_COMMAND_OK);
368 							if (!conn->result)
369 							{
370 								appendPQExpBufferStr(&conn->errorMessage,
371 													 libpq_gettext("out of memory"));
372 								pqSaveErrorResult(conn);
373 							}
374 						}
375 						conn->asyncStatus = PGASYNC_READY;
376 					}
377 					break;
378 				case 't':		/* Parameter Description */
379 					if (getParamDescriptions(conn, msgLength))
380 						return;
381 					break;
382 				case 'D':		/* Data Row */
383 					if (conn->result != NULL &&
384 						conn->result->resultStatus == PGRES_TUPLES_OK)
385 					{
386 						/* Read another tuple of a normal query response */
387 						if (getAnotherTuple(conn, msgLength))
388 							return;
389 					}
390 					else if (conn->result != NULL &&
391 							 conn->result->resultStatus == PGRES_FATAL_ERROR)
392 					{
393 						/*
394 						 * We've already choked for some reason.  Just discard
395 						 * tuples till we get to the end of the query.
396 						 */
397 						conn->inCursor += msgLength;
398 					}
399 					else
400 					{
401 						/* Set up to report error at end of query */
402 						appendPQExpBufferStr(&conn->errorMessage,
403 											 libpq_gettext("server sent data (\"D\" message) without prior row description (\"T\" message)\n"));
404 						pqSaveErrorResult(conn);
405 						/* Discard the unexpected message */
406 						conn->inCursor += msgLength;
407 					}
408 					break;
409 				case 'G':		/* Start Copy In */
410 					if (getCopyStart(conn, PGRES_COPY_IN))
411 						return;
412 					conn->asyncStatus = PGASYNC_COPY_IN;
413 					break;
414 				case 'H':		/* Start Copy Out */
415 					if (getCopyStart(conn, PGRES_COPY_OUT))
416 						return;
417 					conn->asyncStatus = PGASYNC_COPY_OUT;
418 					conn->copy_already_done = 0;
419 					break;
420 				case 'W':		/* Start Copy Both */
421 					if (getCopyStart(conn, PGRES_COPY_BOTH))
422 						return;
423 					conn->asyncStatus = PGASYNC_COPY_BOTH;
424 					conn->copy_already_done = 0;
425 					break;
426 				case 'd':		/* Copy Data */
427 
428 					/*
429 					 * If we see Copy Data, just silently drop it.  This would
430 					 * only occur if application exits COPY OUT mode too
431 					 * early.
432 					 */
433 					conn->inCursor += msgLength;
434 					break;
435 				case 'c':		/* Copy Done */
436 
437 					/*
438 					 * If we see Copy Done, just silently drop it.  This is
439 					 * the normal case during PQendcopy.  We will keep
440 					 * swallowing data, expecting to see command-complete for
441 					 * the COPY command.
442 					 */
443 					break;
444 				default:
445 					appendPQExpBuffer(&conn->errorMessage,
446 									  libpq_gettext("unexpected response from server; first received character was \"%c\"\n"),
447 									  id);
448 					/* build an error result holding the error message */
449 					pqSaveErrorResult(conn);
450 					/* not sure if we will see more, so go to ready state */
451 					conn->asyncStatus = PGASYNC_READY;
452 					/* Discard the unexpected message */
453 					conn->inCursor += msgLength;
454 					break;
455 			}					/* switch on protocol character */
456 		}
457 		/* Successfully consumed this message */
458 		if (conn->inCursor == conn->inStart + 5 + msgLength)
459 		{
460 			/* trace server-to-client message */
461 			if (conn->Pfdebug)
462 				pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
463 
464 			/* Normal case: parsing agrees with specified length */
465 			conn->inStart = conn->inCursor;
466 		}
467 		else
468 		{
469 			/* Trouble --- report it */
470 			appendPQExpBuffer(&conn->errorMessage,
471 							  libpq_gettext("message contents do not agree with length in message type \"%c\"\n"),
472 							  id);
473 			/* build an error result holding the error message */
474 			pqSaveErrorResult(conn);
475 			conn->asyncStatus = PGASYNC_READY;
476 			/* trust the specified message length as what to skip */
477 			conn->inStart += 5 + msgLength;
478 		}
479 	}
480 }
481 
482 /*
483  * handleSyncLoss: clean up after loss of message-boundary sync
484  *
485  * There isn't really a lot we can do here except abandon the connection.
486  */
487 static void
handleSyncLoss(PGconn * conn,char id,int msgLength)488 handleSyncLoss(PGconn *conn, char id, int msgLength)
489 {
490 	appendPQExpBuffer(&conn->errorMessage,
491 					  libpq_gettext("lost synchronization with server: got message type \"%c\", length %d\n"),
492 					  id, msgLength);
493 	/* build an error result holding the error message */
494 	pqSaveErrorResult(conn);
495 	conn->asyncStatus = PGASYNC_READY;	/* drop out of PQgetResult wait loop */
496 	/* flush input data since we're giving up on processing it */
497 	pqDropConnection(conn, true);
498 	conn->status = CONNECTION_BAD;	/* No more connection to backend */
499 }
500 
501 /*
502  * parseInput subroutine to read a 'T' (row descriptions) message.
503  * We'll build a new PGresult structure (unless called for a Describe
504  * command for a prepared statement) containing the attribute data.
505  * Returns: 0 if processed message successfully, EOF to suspend parsing
506  * (the latter case is not actually used currently).
507  */
508 static int
getRowDescriptions(PGconn * conn,int msgLength)509 getRowDescriptions(PGconn *conn, int msgLength)
510 {
511 	PGresult   *result;
512 	int			nfields;
513 	const char *errmsg;
514 	int			i;
515 
516 	/*
517 	 * When doing Describe for a prepared statement, there'll already be a
518 	 * PGresult created by getParamDescriptions, and we should fill data into
519 	 * that.  Otherwise, create a new, empty PGresult.
520 	 */
521 	if (!conn->cmd_queue_head ||
522 		(conn->cmd_queue_head &&
523 		 conn->cmd_queue_head->queryclass == PGQUERY_DESCRIBE))
524 	{
525 		if (conn->result)
526 			result = conn->result;
527 		else
528 			result = PQmakeEmptyPGresult(conn, PGRES_COMMAND_OK);
529 	}
530 	else
531 		result = PQmakeEmptyPGresult(conn, PGRES_TUPLES_OK);
532 	if (!result)
533 	{
534 		errmsg = NULL;			/* means "out of memory", see below */
535 		goto advance_and_error;
536 	}
537 
538 	/* parseInput already read the 'T' label and message length. */
539 	/* the next two bytes are the number of fields */
540 	if (pqGetInt(&(result->numAttributes), 2, conn))
541 	{
542 		/* We should not run out of data here, so complain */
543 		errmsg = libpq_gettext("insufficient data in \"T\" message");
544 		goto advance_and_error;
545 	}
546 	nfields = result->numAttributes;
547 
548 	/* allocate space for the attribute descriptors */
549 	if (nfields > 0)
550 	{
551 		result->attDescs = (PGresAttDesc *)
552 			pqResultAlloc(result, nfields * sizeof(PGresAttDesc), true);
553 		if (!result->attDescs)
554 		{
555 			errmsg = NULL;		/* means "out of memory", see below */
556 			goto advance_and_error;
557 		}
558 		MemSet(result->attDescs, 0, nfields * sizeof(PGresAttDesc));
559 	}
560 
561 	/* result->binary is true only if ALL columns are binary */
562 	result->binary = (nfields > 0) ? 1 : 0;
563 
564 	/* get type info */
565 	for (i = 0; i < nfields; i++)
566 	{
567 		int			tableid;
568 		int			columnid;
569 		int			typid;
570 		int			typlen;
571 		int			atttypmod;
572 		int			format;
573 
574 		if (pqGets(&conn->workBuffer, conn) ||
575 			pqGetInt(&tableid, 4, conn) ||
576 			pqGetInt(&columnid, 2, conn) ||
577 			pqGetInt(&typid, 4, conn) ||
578 			pqGetInt(&typlen, 2, conn) ||
579 			pqGetInt(&atttypmod, 4, conn) ||
580 			pqGetInt(&format, 2, conn))
581 		{
582 			/* We should not run out of data here, so complain */
583 			errmsg = libpq_gettext("insufficient data in \"T\" message");
584 			goto advance_and_error;
585 		}
586 
587 		/*
588 		 * Since pqGetInt treats 2-byte integers as unsigned, we need to
589 		 * coerce these results to signed form.
590 		 */
591 		columnid = (int) ((int16) columnid);
592 		typlen = (int) ((int16) typlen);
593 		format = (int) ((int16) format);
594 
595 		result->attDescs[i].name = pqResultStrdup(result,
596 												  conn->workBuffer.data);
597 		if (!result->attDescs[i].name)
598 		{
599 			errmsg = NULL;		/* means "out of memory", see below */
600 			goto advance_and_error;
601 		}
602 		result->attDescs[i].tableid = tableid;
603 		result->attDescs[i].columnid = columnid;
604 		result->attDescs[i].format = format;
605 		result->attDescs[i].typid = typid;
606 		result->attDescs[i].typlen = typlen;
607 		result->attDescs[i].atttypmod = atttypmod;
608 
609 		if (format != 1)
610 			result->binary = 0;
611 	}
612 
613 	/* Success! */
614 	conn->result = result;
615 
616 	/*
617 	 * If we're doing a Describe, we're done, and ready to pass the result
618 	 * back to the client.
619 	 */
620 	if ((!conn->cmd_queue_head) ||
621 		(conn->cmd_queue_head &&
622 		 conn->cmd_queue_head->queryclass == PGQUERY_DESCRIBE))
623 	{
624 		conn->asyncStatus = PGASYNC_READY;
625 		return 0;
626 	}
627 
628 	/*
629 	 * We could perform additional setup for the new result set here, but for
630 	 * now there's nothing else to do.
631 	 */
632 
633 	/* And we're done. */
634 	return 0;
635 
636 advance_and_error:
637 	/* Discard unsaved result, if any */
638 	if (result && result != conn->result)
639 		PQclear(result);
640 
641 	/*
642 	 * Replace partially constructed result with an error result. First
643 	 * discard the old result to try to win back some memory.
644 	 */
645 	pqClearAsyncResult(conn);
646 
647 	/*
648 	 * If preceding code didn't provide an error message, assume "out of
649 	 * memory" was meant.  The advantage of having this special case is that
650 	 * freeing the old result first greatly improves the odds that gettext()
651 	 * will succeed in providing a translation.
652 	 */
653 	if (!errmsg)
654 		errmsg = libpq_gettext("out of memory for query result");
655 
656 	appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
657 	pqSaveErrorResult(conn);
658 
659 	/*
660 	 * Show the message as fully consumed, else pqParseInput3 will overwrite
661 	 * our error with a complaint about that.
662 	 */
663 	conn->inCursor = conn->inStart + 5 + msgLength;
664 
665 	/*
666 	 * Return zero to allow input parsing to continue.  Subsequent "D"
667 	 * messages will be ignored until we get to end of data, since an error
668 	 * result is already set up.
669 	 */
670 	return 0;
671 }
672 
673 /*
674  * parseInput subroutine to read a 't' (ParameterDescription) message.
675  * We'll build a new PGresult structure containing the parameter data.
676  * Returns: 0 if processed message successfully, EOF to suspend parsing
677  * (the latter case is not actually used currently).
678  */
679 static int
getParamDescriptions(PGconn * conn,int msgLength)680 getParamDescriptions(PGconn *conn, int msgLength)
681 {
682 	PGresult   *result;
683 	const char *errmsg = NULL;	/* means "out of memory", see below */
684 	int			nparams;
685 	int			i;
686 
687 	result = PQmakeEmptyPGresult(conn, PGRES_COMMAND_OK);
688 	if (!result)
689 		goto advance_and_error;
690 
691 	/* parseInput already read the 't' label and message length. */
692 	/* the next two bytes are the number of parameters */
693 	if (pqGetInt(&(result->numParameters), 2, conn))
694 		goto not_enough_data;
695 	nparams = result->numParameters;
696 
697 	/* allocate space for the parameter descriptors */
698 	if (nparams > 0)
699 	{
700 		result->paramDescs = (PGresParamDesc *)
701 			pqResultAlloc(result, nparams * sizeof(PGresParamDesc), true);
702 		if (!result->paramDescs)
703 			goto advance_and_error;
704 		MemSet(result->paramDescs, 0, nparams * sizeof(PGresParamDesc));
705 	}
706 
707 	/* get parameter info */
708 	for (i = 0; i < nparams; i++)
709 	{
710 		int			typid;
711 
712 		if (pqGetInt(&typid, 4, conn))
713 			goto not_enough_data;
714 		result->paramDescs[i].typid = typid;
715 	}
716 
717 	/* Success! */
718 	conn->result = result;
719 
720 	return 0;
721 
722 not_enough_data:
723 	errmsg = libpq_gettext("insufficient data in \"t\" message");
724 
725 advance_and_error:
726 	/* Discard unsaved result, if any */
727 	if (result && result != conn->result)
728 		PQclear(result);
729 
730 	/*
731 	 * Replace partially constructed result with an error result. First
732 	 * discard the old result to try to win back some memory.
733 	 */
734 	pqClearAsyncResult(conn);
735 
736 	/*
737 	 * If preceding code didn't provide an error message, assume "out of
738 	 * memory" was meant.  The advantage of having this special case is that
739 	 * freeing the old result first greatly improves the odds that gettext()
740 	 * will succeed in providing a translation.
741 	 */
742 	if (!errmsg)
743 		errmsg = libpq_gettext("out of memory");
744 	appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
745 	pqSaveErrorResult(conn);
746 
747 	/*
748 	 * Show the message as fully consumed, else pqParseInput3 will overwrite
749 	 * our error with a complaint about that.
750 	 */
751 	conn->inCursor = conn->inStart + 5 + msgLength;
752 
753 	/*
754 	 * Return zero to allow input parsing to continue.  Essentially, we've
755 	 * replaced the COMMAND_OK result with an error result, but since this
756 	 * doesn't affect the protocol state, it's fine.
757 	 */
758 	return 0;
759 }
760 
761 /*
762  * parseInput subroutine to read a 'D' (row data) message.
763  * We fill rowbuf with column pointers and then call the row processor.
764  * Returns: 0 if processed message successfully, EOF to suspend parsing
765  * (the latter case is not actually used currently).
766  */
767 static int
getAnotherTuple(PGconn * conn,int msgLength)768 getAnotherTuple(PGconn *conn, int msgLength)
769 {
770 	PGresult   *result = conn->result;
771 	int			nfields = result->numAttributes;
772 	const char *errmsg;
773 	PGdataValue *rowbuf;
774 	int			tupnfields;		/* # fields from tuple */
775 	int			vlen;			/* length of the current field value */
776 	int			i;
777 
778 	/* Get the field count and make sure it's what we expect */
779 	if (pqGetInt(&tupnfields, 2, conn))
780 	{
781 		/* We should not run out of data here, so complain */
782 		errmsg = libpq_gettext("insufficient data in \"D\" message");
783 		goto advance_and_error;
784 	}
785 
786 	if (tupnfields != nfields)
787 	{
788 		errmsg = libpq_gettext("unexpected field count in \"D\" message");
789 		goto advance_and_error;
790 	}
791 
792 	/* Resize row buffer if needed */
793 	rowbuf = conn->rowBuf;
794 	if (nfields > conn->rowBufLen)
795 	{
796 		rowbuf = (PGdataValue *) realloc(rowbuf,
797 										 nfields * sizeof(PGdataValue));
798 		if (!rowbuf)
799 		{
800 			errmsg = NULL;		/* means "out of memory", see below */
801 			goto advance_and_error;
802 		}
803 		conn->rowBuf = rowbuf;
804 		conn->rowBufLen = nfields;
805 	}
806 
807 	/* Scan the fields */
808 	for (i = 0; i < nfields; i++)
809 	{
810 		/* get the value length */
811 		if (pqGetInt(&vlen, 4, conn))
812 		{
813 			/* We should not run out of data here, so complain */
814 			errmsg = libpq_gettext("insufficient data in \"D\" message");
815 			goto advance_and_error;
816 		}
817 		rowbuf[i].len = vlen;
818 
819 		/*
820 		 * rowbuf[i].value always points to the next address in the data
821 		 * buffer even if the value is NULL.  This allows row processors to
822 		 * estimate data sizes more easily.
823 		 */
824 		rowbuf[i].value = conn->inBuffer + conn->inCursor;
825 
826 		/* Skip over the data value */
827 		if (vlen > 0)
828 		{
829 			if (pqSkipnchar(vlen, conn))
830 			{
831 				/* We should not run out of data here, so complain */
832 				errmsg = libpq_gettext("insufficient data in \"D\" message");
833 				goto advance_and_error;
834 			}
835 		}
836 	}
837 
838 	/* Process the collected row */
839 	errmsg = NULL;
840 	if (pqRowProcessor(conn, &errmsg))
841 		return 0;				/* normal, successful exit */
842 
843 	/* pqRowProcessor failed, fall through to report it */
844 
845 advance_and_error:
846 
847 	/*
848 	 * Replace partially constructed result with an error result. First
849 	 * discard the old result to try to win back some memory.
850 	 */
851 	pqClearAsyncResult(conn);
852 
853 	/*
854 	 * If preceding code didn't provide an error message, assume "out of
855 	 * memory" was meant.  The advantage of having this special case is that
856 	 * freeing the old result first greatly improves the odds that gettext()
857 	 * will succeed in providing a translation.
858 	 */
859 	if (!errmsg)
860 		errmsg = libpq_gettext("out of memory for query result");
861 
862 	appendPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
863 	pqSaveErrorResult(conn);
864 
865 	/*
866 	 * Show the message as fully consumed, else pqParseInput3 will overwrite
867 	 * our error with a complaint about that.
868 	 */
869 	conn->inCursor = conn->inStart + 5 + msgLength;
870 
871 	/*
872 	 * Return zero to allow input parsing to continue.  Subsequent "D"
873 	 * messages will be ignored until we get to end of data, since an error
874 	 * result is already set up.
875 	 */
876 	return 0;
877 }
878 
879 
880 /*
881  * Attempt to read an Error or Notice response message.
882  * This is possible in several places, so we break it out as a subroutine.
883  * Entry: 'E' or 'N' message type and length have already been consumed.
884  * Exit: returns 0 if successfully consumed message.
885  *		 returns EOF if not enough data.
886  */
887 int
pqGetErrorNotice3(PGconn * conn,bool isError)888 pqGetErrorNotice3(PGconn *conn, bool isError)
889 {
890 	PGresult   *res = NULL;
891 	bool		have_position = false;
892 	PQExpBufferData workBuf;
893 	char		id;
894 
895 	/* If in pipeline mode, set error indicator for it */
896 	if (isError && conn->pipelineStatus != PQ_PIPELINE_OFF)
897 		conn->pipelineStatus = PQ_PIPELINE_ABORTED;
898 
899 	/*
900 	 * If this is an error message, pre-emptively clear any incomplete query
901 	 * result we may have.  We'd just throw it away below anyway, and
902 	 * releasing it before collecting the error might avoid out-of-memory.
903 	 */
904 	if (isError)
905 		pqClearAsyncResult(conn);
906 
907 	/*
908 	 * Since the fields might be pretty long, we create a temporary
909 	 * PQExpBuffer rather than using conn->workBuffer.  workBuffer is intended
910 	 * for stuff that is expected to be short.  We shouldn't use
911 	 * conn->errorMessage either, since this might be only a notice.
912 	 */
913 	initPQExpBuffer(&workBuf);
914 
915 	/*
916 	 * Make a PGresult to hold the accumulated fields.  We temporarily lie
917 	 * about the result status, so that PQmakeEmptyPGresult doesn't uselessly
918 	 * copy conn->errorMessage.
919 	 *
920 	 * NB: This allocation can fail, if you run out of memory. The rest of the
921 	 * function handles that gracefully, and we still try to set the error
922 	 * message as the connection's error message.
923 	 */
924 	res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY);
925 	if (res)
926 		res->resultStatus = isError ? PGRES_FATAL_ERROR : PGRES_NONFATAL_ERROR;
927 
928 	/*
929 	 * Read the fields and save into res.
930 	 *
931 	 * While at it, save the SQLSTATE in conn->last_sqlstate, and note whether
932 	 * we saw a PG_DIAG_STATEMENT_POSITION field.
933 	 */
934 	for (;;)
935 	{
936 		if (pqGetc(&id, conn))
937 			goto fail;
938 		if (id == '\0')
939 			break;				/* terminator found */
940 		if (pqGets(&workBuf, conn))
941 			goto fail;
942 		pqSaveMessageField(res, id, workBuf.data);
943 		if (id == PG_DIAG_SQLSTATE)
944 			strlcpy(conn->last_sqlstate, workBuf.data,
945 					sizeof(conn->last_sqlstate));
946 		else if (id == PG_DIAG_STATEMENT_POSITION)
947 			have_position = true;
948 	}
949 
950 	/*
951 	 * Save the active query text, if any, into res as well; but only if we
952 	 * might need it for an error cursor display, which is only true if there
953 	 * is a PG_DIAG_STATEMENT_POSITION field.
954 	 */
955 	if (have_position && res && conn->cmd_queue_head && conn->cmd_queue_head->query)
956 		res->errQuery = pqResultStrdup(res, conn->cmd_queue_head->query);
957 
958 	/*
959 	 * Now build the "overall" error message for PQresultErrorMessage.
960 	 */
961 	resetPQExpBuffer(&workBuf);
962 	pqBuildErrorMessage3(&workBuf, res, conn->verbosity, conn->show_context);
963 
964 	/*
965 	 * Either save error as current async result, or just emit the notice.
966 	 */
967 	if (isError)
968 	{
969 		if (res)
970 			pqSetResultError(res, &workBuf);
971 		pqClearAsyncResult(conn);	/* redundant, but be safe */
972 		conn->result = res;
973 		if (PQExpBufferDataBroken(workBuf))
974 			appendPQExpBufferStr(&conn->errorMessage,
975 								 libpq_gettext("out of memory\n"));
976 		else
977 			appendPQExpBufferStr(&conn->errorMessage, workBuf.data);
978 	}
979 	else
980 	{
981 		/* if we couldn't allocate the result set, just discard the NOTICE */
982 		if (res)
983 		{
984 			/*
985 			 * We can cheat a little here and not copy the message.  But if we
986 			 * were unlucky enough to run out of memory while filling workBuf,
987 			 * insert "out of memory", as in pqSetResultError.
988 			 */
989 			if (PQExpBufferDataBroken(workBuf))
990 				res->errMsg = libpq_gettext("out of memory\n");
991 			else
992 				res->errMsg = workBuf.data;
993 			if (res->noticeHooks.noticeRec != NULL)
994 				res->noticeHooks.noticeRec(res->noticeHooks.noticeRecArg, res);
995 			PQclear(res);
996 		}
997 	}
998 
999 	termPQExpBuffer(&workBuf);
1000 	return 0;
1001 
1002 fail:
1003 	PQclear(res);
1004 	termPQExpBuffer(&workBuf);
1005 	return EOF;
1006 }
1007 
1008 /*
1009  * Construct an error message from the fields in the given PGresult,
1010  * appending it to the contents of "msg".
1011  */
1012 void
pqBuildErrorMessage3(PQExpBuffer msg,const PGresult * res,PGVerbosity verbosity,PGContextVisibility show_context)1013 pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res,
1014 					 PGVerbosity verbosity, PGContextVisibility show_context)
1015 {
1016 	const char *val;
1017 	const char *querytext = NULL;
1018 	int			querypos = 0;
1019 
1020 	/* If we couldn't allocate a PGresult, just say "out of memory" */
1021 	if (res == NULL)
1022 	{
1023 		appendPQExpBufferStr(msg, libpq_gettext("out of memory\n"));
1024 		return;
1025 	}
1026 
1027 	/*
1028 	 * If we don't have any broken-down fields, just return the base message.
1029 	 * This mainly applies if we're given a libpq-generated error result.
1030 	 */
1031 	if (res->errFields == NULL)
1032 	{
1033 		if (res->errMsg && res->errMsg[0])
1034 			appendPQExpBufferStr(msg, res->errMsg);
1035 		else
1036 			appendPQExpBufferStr(msg, libpq_gettext("no error message available\n"));
1037 		return;
1038 	}
1039 
1040 	/* Else build error message from relevant fields */
1041 	val = PQresultErrorField(res, PG_DIAG_SEVERITY);
1042 	if (val)
1043 		appendPQExpBuffer(msg, "%s:  ", val);
1044 
1045 	if (verbosity == PQERRORS_SQLSTATE)
1046 	{
1047 		/*
1048 		 * If we have a SQLSTATE, print that and nothing else.  If not (which
1049 		 * shouldn't happen for server-generated errors, but might possibly
1050 		 * happen for libpq-generated ones), fall back to TERSE format, as
1051 		 * that seems better than printing nothing at all.
1052 		 */
1053 		val = PQresultErrorField(res, PG_DIAG_SQLSTATE);
1054 		if (val)
1055 		{
1056 			appendPQExpBuffer(msg, "%s\n", val);
1057 			return;
1058 		}
1059 		verbosity = PQERRORS_TERSE;
1060 	}
1061 
1062 	if (verbosity == PQERRORS_VERBOSE)
1063 	{
1064 		val = PQresultErrorField(res, PG_DIAG_SQLSTATE);
1065 		if (val)
1066 			appendPQExpBuffer(msg, "%s: ", val);
1067 	}
1068 	val = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
1069 	if (val)
1070 		appendPQExpBufferStr(msg, val);
1071 	val = PQresultErrorField(res, PG_DIAG_STATEMENT_POSITION);
1072 	if (val)
1073 	{
1074 		if (verbosity != PQERRORS_TERSE && res->errQuery != NULL)
1075 		{
1076 			/* emit position as a syntax cursor display */
1077 			querytext = res->errQuery;
1078 			querypos = atoi(val);
1079 		}
1080 		else
1081 		{
1082 			/* emit position as text addition to primary message */
1083 			/* translator: %s represents a digit string */
1084 			appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1085 							  val);
1086 		}
1087 	}
1088 	else
1089 	{
1090 		val = PQresultErrorField(res, PG_DIAG_INTERNAL_POSITION);
1091 		if (val)
1092 		{
1093 			querytext = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
1094 			if (verbosity != PQERRORS_TERSE && querytext != NULL)
1095 			{
1096 				/* emit position as a syntax cursor display */
1097 				querypos = atoi(val);
1098 			}
1099 			else
1100 			{
1101 				/* emit position as text addition to primary message */
1102 				/* translator: %s represents a digit string */
1103 				appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1104 								  val);
1105 			}
1106 		}
1107 	}
1108 	appendPQExpBufferChar(msg, '\n');
1109 	if (verbosity != PQERRORS_TERSE)
1110 	{
1111 		if (querytext && querypos > 0)
1112 			reportErrorPosition(msg, querytext, querypos,
1113 								res->client_encoding);
1114 		val = PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL);
1115 		if (val)
1116 			appendPQExpBuffer(msg, libpq_gettext("DETAIL:  %s\n"), val);
1117 		val = PQresultErrorField(res, PG_DIAG_MESSAGE_HINT);
1118 		if (val)
1119 			appendPQExpBuffer(msg, libpq_gettext("HINT:  %s\n"), val);
1120 		val = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
1121 		if (val)
1122 			appendPQExpBuffer(msg, libpq_gettext("QUERY:  %s\n"), val);
1123 		if (show_context == PQSHOW_CONTEXT_ALWAYS ||
1124 			(show_context == PQSHOW_CONTEXT_ERRORS &&
1125 			 res->resultStatus == PGRES_FATAL_ERROR))
1126 		{
1127 			val = PQresultErrorField(res, PG_DIAG_CONTEXT);
1128 			if (val)
1129 				appendPQExpBuffer(msg, libpq_gettext("CONTEXT:  %s\n"),
1130 								  val);
1131 		}
1132 	}
1133 	if (verbosity == PQERRORS_VERBOSE)
1134 	{
1135 		val = PQresultErrorField(res, PG_DIAG_SCHEMA_NAME);
1136 		if (val)
1137 			appendPQExpBuffer(msg,
1138 							  libpq_gettext("SCHEMA NAME:  %s\n"), val);
1139 		val = PQresultErrorField(res, PG_DIAG_TABLE_NAME);
1140 		if (val)
1141 			appendPQExpBuffer(msg,
1142 							  libpq_gettext("TABLE NAME:  %s\n"), val);
1143 		val = PQresultErrorField(res, PG_DIAG_COLUMN_NAME);
1144 		if (val)
1145 			appendPQExpBuffer(msg,
1146 							  libpq_gettext("COLUMN NAME:  %s\n"), val);
1147 		val = PQresultErrorField(res, PG_DIAG_DATATYPE_NAME);
1148 		if (val)
1149 			appendPQExpBuffer(msg,
1150 							  libpq_gettext("DATATYPE NAME:  %s\n"), val);
1151 		val = PQresultErrorField(res, PG_DIAG_CONSTRAINT_NAME);
1152 		if (val)
1153 			appendPQExpBuffer(msg,
1154 							  libpq_gettext("CONSTRAINT NAME:  %s\n"), val);
1155 	}
1156 	if (verbosity == PQERRORS_VERBOSE)
1157 	{
1158 		const char *valf;
1159 		const char *vall;
1160 
1161 		valf = PQresultErrorField(res, PG_DIAG_SOURCE_FILE);
1162 		vall = PQresultErrorField(res, PG_DIAG_SOURCE_LINE);
1163 		val = PQresultErrorField(res, PG_DIAG_SOURCE_FUNCTION);
1164 		if (val || valf || vall)
1165 		{
1166 			appendPQExpBufferStr(msg, libpq_gettext("LOCATION:  "));
1167 			if (val)
1168 				appendPQExpBuffer(msg, libpq_gettext("%s, "), val);
1169 			if (valf && vall)	/* unlikely we'd have just one */
1170 				appendPQExpBuffer(msg, libpq_gettext("%s:%s"),
1171 								  valf, vall);
1172 			appendPQExpBufferChar(msg, '\n');
1173 		}
1174 	}
1175 }
1176 
1177 /*
1178  * Add an error-location display to the error message under construction.
1179  *
1180  * The cursor location is measured in logical characters; the query string
1181  * is presumed to be in the specified encoding.
1182  */
1183 static void
reportErrorPosition(PQExpBuffer msg,const char * query,int loc,int encoding)1184 reportErrorPosition(PQExpBuffer msg, const char *query, int loc, int encoding)
1185 {
1186 #define DISPLAY_SIZE	60		/* screen width limit, in screen cols */
1187 #define MIN_RIGHT_CUT	10		/* try to keep this far away from EOL */
1188 
1189 	char	   *wquery;
1190 	int			slen,
1191 				cno,
1192 				i,
1193 			   *qidx,
1194 			   *scridx,
1195 				qoffset,
1196 				scroffset,
1197 				ibeg,
1198 				iend,
1199 				loc_line;
1200 	bool		mb_encoding,
1201 				beg_trunc,
1202 				end_trunc;
1203 
1204 	/* Convert loc from 1-based to 0-based; no-op if out of range */
1205 	loc--;
1206 	if (loc < 0)
1207 		return;
1208 
1209 	/* Need a writable copy of the query */
1210 	wquery = strdup(query);
1211 	if (wquery == NULL)
1212 		return;					/* fail silently if out of memory */
1213 
1214 	/*
1215 	 * Each character might occupy multiple physical bytes in the string, and
1216 	 * in some Far Eastern character sets it might take more than one screen
1217 	 * column as well.  We compute the starting byte offset and starting
1218 	 * screen column of each logical character, and store these in qidx[] and
1219 	 * scridx[] respectively.
1220 	 */
1221 
1222 	/* we need a safe allocation size... */
1223 	slen = strlen(wquery) + 1;
1224 
1225 	qidx = (int *) malloc(slen * sizeof(int));
1226 	if (qidx == NULL)
1227 	{
1228 		free(wquery);
1229 		return;
1230 	}
1231 	scridx = (int *) malloc(slen * sizeof(int));
1232 	if (scridx == NULL)
1233 	{
1234 		free(qidx);
1235 		free(wquery);
1236 		return;
1237 	}
1238 
1239 	/* We can optimize a bit if it's a single-byte encoding */
1240 	mb_encoding = (pg_encoding_max_length(encoding) != 1);
1241 
1242 	/*
1243 	 * Within the scanning loop, cno is the current character's logical
1244 	 * number, qoffset is its offset in wquery, and scroffset is its starting
1245 	 * logical screen column (all indexed from 0).  "loc" is the logical
1246 	 * character number of the error location.  We scan to determine loc_line
1247 	 * (the 1-based line number containing loc) and ibeg/iend (first character
1248 	 * number and last+1 character number of the line containing loc). Note
1249 	 * that qidx[] and scridx[] are filled only as far as iend.
1250 	 */
1251 	qoffset = 0;
1252 	scroffset = 0;
1253 	loc_line = 1;
1254 	ibeg = 0;
1255 	iend = -1;					/* -1 means not set yet */
1256 
1257 	for (cno = 0; wquery[qoffset] != '\0'; cno++)
1258 	{
1259 		char		ch = wquery[qoffset];
1260 
1261 		qidx[cno] = qoffset;
1262 		scridx[cno] = scroffset;
1263 
1264 		/*
1265 		 * Replace tabs with spaces in the writable copy.  (Later we might
1266 		 * want to think about coping with their variable screen width, but
1267 		 * not today.)
1268 		 */
1269 		if (ch == '\t')
1270 			wquery[qoffset] = ' ';
1271 
1272 		/*
1273 		 * If end-of-line, count lines and mark positions. Each \r or \n
1274 		 * counts as a line except when \r \n appear together.
1275 		 */
1276 		else if (ch == '\r' || ch == '\n')
1277 		{
1278 			if (cno < loc)
1279 			{
1280 				if (ch == '\r' ||
1281 					cno == 0 ||
1282 					wquery[qidx[cno - 1]] != '\r')
1283 					loc_line++;
1284 				/* extract beginning = last line start before loc. */
1285 				ibeg = cno + 1;
1286 			}
1287 			else
1288 			{
1289 				/* set extract end. */
1290 				iend = cno;
1291 				/* done scanning. */
1292 				break;
1293 			}
1294 		}
1295 
1296 		/* Advance */
1297 		if (mb_encoding)
1298 		{
1299 			int			w;
1300 
1301 			w = pg_encoding_dsplen(encoding, &wquery[qoffset]);
1302 			/* treat any non-tab control chars as width 1 */
1303 			if (w <= 0)
1304 				w = 1;
1305 			scroffset += w;
1306 			qoffset += PQmblenBounded(&wquery[qoffset], encoding);
1307 		}
1308 		else
1309 		{
1310 			/* We assume wide chars only exist in multibyte encodings */
1311 			scroffset++;
1312 			qoffset++;
1313 		}
1314 	}
1315 	/* Fix up if we didn't find an end-of-line after loc */
1316 	if (iend < 0)
1317 	{
1318 		iend = cno;				/* query length in chars, +1 */
1319 		qidx[iend] = qoffset;
1320 		scridx[iend] = scroffset;
1321 	}
1322 
1323 	/* Print only if loc is within computed query length */
1324 	if (loc <= cno)
1325 	{
1326 		/* If the line extracted is too long, we truncate it. */
1327 		beg_trunc = false;
1328 		end_trunc = false;
1329 		if (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
1330 		{
1331 			/*
1332 			 * We first truncate right if it is enough.  This code might be
1333 			 * off a space or so on enforcing MIN_RIGHT_CUT if there's a wide
1334 			 * character right there, but that should be okay.
1335 			 */
1336 			if (scridx[ibeg] + DISPLAY_SIZE >= scridx[loc] + MIN_RIGHT_CUT)
1337 			{
1338 				while (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
1339 					iend--;
1340 				end_trunc = true;
1341 			}
1342 			else
1343 			{
1344 				/* Truncate right if not too close to loc. */
1345 				while (scridx[loc] + MIN_RIGHT_CUT < scridx[iend])
1346 				{
1347 					iend--;
1348 					end_trunc = true;
1349 				}
1350 
1351 				/* Truncate left if still too long. */
1352 				while (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
1353 				{
1354 					ibeg++;
1355 					beg_trunc = true;
1356 				}
1357 			}
1358 		}
1359 
1360 		/* truncate working copy at desired endpoint */
1361 		wquery[qidx[iend]] = '\0';
1362 
1363 		/* Begin building the finished message. */
1364 		i = msg->len;
1365 		appendPQExpBuffer(msg, libpq_gettext("LINE %d: "), loc_line);
1366 		if (beg_trunc)
1367 			appendPQExpBufferStr(msg, "...");
1368 
1369 		/*
1370 		 * While we have the prefix in the msg buffer, compute its screen
1371 		 * width.
1372 		 */
1373 		scroffset = 0;
1374 		for (; i < msg->len; i += PQmblenBounded(&msg->data[i], encoding))
1375 		{
1376 			int			w = pg_encoding_dsplen(encoding, &msg->data[i]);
1377 
1378 			if (w <= 0)
1379 				w = 1;
1380 			scroffset += w;
1381 		}
1382 
1383 		/* Finish up the LINE message line. */
1384 		appendPQExpBufferStr(msg, &wquery[qidx[ibeg]]);
1385 		if (end_trunc)
1386 			appendPQExpBufferStr(msg, "...");
1387 		appendPQExpBufferChar(msg, '\n');
1388 
1389 		/* Now emit the cursor marker line. */
1390 		scroffset += scridx[loc] - scridx[ibeg];
1391 		for (i = 0; i < scroffset; i++)
1392 			appendPQExpBufferChar(msg, ' ');
1393 		appendPQExpBufferChar(msg, '^');
1394 		appendPQExpBufferChar(msg, '\n');
1395 	}
1396 
1397 	/* Clean up. */
1398 	free(scridx);
1399 	free(qidx);
1400 	free(wquery);
1401 }
1402 
1403 
1404 /*
1405  * Attempt to read a ParameterStatus message.
1406  * This is possible in several places, so we break it out as a subroutine.
1407  * Entry: 'S' message type and length have already been consumed.
1408  * Exit: returns 0 if successfully consumed message.
1409  *		 returns EOF if not enough data.
1410  */
1411 static int
getParameterStatus(PGconn * conn)1412 getParameterStatus(PGconn *conn)
1413 {
1414 	PQExpBufferData valueBuf;
1415 
1416 	/* Get the parameter name */
1417 	if (pqGets(&conn->workBuffer, conn))
1418 		return EOF;
1419 	/* Get the parameter value (could be large) */
1420 	initPQExpBuffer(&valueBuf);
1421 	if (pqGets(&valueBuf, conn))
1422 	{
1423 		termPQExpBuffer(&valueBuf);
1424 		return EOF;
1425 	}
1426 	/* And save it */
1427 	pqSaveParameterStatus(conn, conn->workBuffer.data, valueBuf.data);
1428 	termPQExpBuffer(&valueBuf);
1429 	return 0;
1430 }
1431 
1432 
1433 /*
1434  * Attempt to read a Notify response message.
1435  * This is possible in several places, so we break it out as a subroutine.
1436  * Entry: 'A' message type and length have already been consumed.
1437  * Exit: returns 0 if successfully consumed Notify message.
1438  *		 returns EOF if not enough data.
1439  */
1440 static int
getNotify(PGconn * conn)1441 getNotify(PGconn *conn)
1442 {
1443 	int			be_pid;
1444 	char	   *svname;
1445 	int			nmlen;
1446 	int			extralen;
1447 	PGnotify   *newNotify;
1448 
1449 	if (pqGetInt(&be_pid, 4, conn))
1450 		return EOF;
1451 	if (pqGets(&conn->workBuffer, conn))
1452 		return EOF;
1453 	/* must save name while getting extra string */
1454 	svname = strdup(conn->workBuffer.data);
1455 	if (!svname)
1456 		return EOF;
1457 	if (pqGets(&conn->workBuffer, conn))
1458 	{
1459 		free(svname);
1460 		return EOF;
1461 	}
1462 
1463 	/*
1464 	 * Store the strings right after the PQnotify structure so it can all be
1465 	 * freed at once.  We don't use NAMEDATALEN because we don't want to tie
1466 	 * this interface to a specific server name length.
1467 	 */
1468 	nmlen = strlen(svname);
1469 	extralen = strlen(conn->workBuffer.data);
1470 	newNotify = (PGnotify *) malloc(sizeof(PGnotify) + nmlen + extralen + 2);
1471 	if (newNotify)
1472 	{
1473 		newNotify->relname = (char *) newNotify + sizeof(PGnotify);
1474 		strcpy(newNotify->relname, svname);
1475 		newNotify->extra = newNotify->relname + nmlen + 1;
1476 		strcpy(newNotify->extra, conn->workBuffer.data);
1477 		newNotify->be_pid = be_pid;
1478 		newNotify->next = NULL;
1479 		if (conn->notifyTail)
1480 			conn->notifyTail->next = newNotify;
1481 		else
1482 			conn->notifyHead = newNotify;
1483 		conn->notifyTail = newNotify;
1484 	}
1485 
1486 	free(svname);
1487 	return 0;
1488 }
1489 
1490 /*
1491  * getCopyStart - process CopyInResponse, CopyOutResponse or
1492  * CopyBothResponse message
1493  *
1494  * parseInput already read the message type and length.
1495  */
1496 static int
getCopyStart(PGconn * conn,ExecStatusType copytype)1497 getCopyStart(PGconn *conn, ExecStatusType copytype)
1498 {
1499 	PGresult   *result;
1500 	int			nfields;
1501 	int			i;
1502 
1503 	result = PQmakeEmptyPGresult(conn, copytype);
1504 	if (!result)
1505 		goto failure;
1506 
1507 	if (pqGetc(&conn->copy_is_binary, conn))
1508 		goto failure;
1509 	result->binary = conn->copy_is_binary;
1510 	/* the next two bytes are the number of fields	*/
1511 	if (pqGetInt(&(result->numAttributes), 2, conn))
1512 		goto failure;
1513 	nfields = result->numAttributes;
1514 
1515 	/* allocate space for the attribute descriptors */
1516 	if (nfields > 0)
1517 	{
1518 		result->attDescs = (PGresAttDesc *)
1519 			pqResultAlloc(result, nfields * sizeof(PGresAttDesc), true);
1520 		if (!result->attDescs)
1521 			goto failure;
1522 		MemSet(result->attDescs, 0, nfields * sizeof(PGresAttDesc));
1523 	}
1524 
1525 	for (i = 0; i < nfields; i++)
1526 	{
1527 		int			format;
1528 
1529 		if (pqGetInt(&format, 2, conn))
1530 			goto failure;
1531 
1532 		/*
1533 		 * Since pqGetInt treats 2-byte integers as unsigned, we need to
1534 		 * coerce these results to signed form.
1535 		 */
1536 		format = (int) ((int16) format);
1537 		result->attDescs[i].format = format;
1538 	}
1539 
1540 	/* Success! */
1541 	conn->result = result;
1542 	return 0;
1543 
1544 failure:
1545 	PQclear(result);
1546 	return EOF;
1547 }
1548 
1549 /*
1550  * getReadyForQuery - process ReadyForQuery message
1551  */
1552 static int
getReadyForQuery(PGconn * conn)1553 getReadyForQuery(PGconn *conn)
1554 {
1555 	char		xact_status;
1556 
1557 	if (pqGetc(&xact_status, conn))
1558 		return EOF;
1559 	switch (xact_status)
1560 	{
1561 		case 'I':
1562 			conn->xactStatus = PQTRANS_IDLE;
1563 			break;
1564 		case 'T':
1565 			conn->xactStatus = PQTRANS_INTRANS;
1566 			break;
1567 		case 'E':
1568 			conn->xactStatus = PQTRANS_INERROR;
1569 			break;
1570 		default:
1571 			conn->xactStatus = PQTRANS_UNKNOWN;
1572 			break;
1573 	}
1574 
1575 	return 0;
1576 }
1577 
1578 /*
1579  * getCopyDataMessage - fetch next CopyData message, process async messages
1580  *
1581  * Returns length word of CopyData message (> 0), or 0 if no complete
1582  * message available, -1 if end of copy, -2 if error.
1583  */
1584 static int
getCopyDataMessage(PGconn * conn)1585 getCopyDataMessage(PGconn *conn)
1586 {
1587 	char		id;
1588 	int			msgLength;
1589 	int			avail;
1590 
1591 	for (;;)
1592 	{
1593 		/*
1594 		 * Do we have the next input message?  To make life simpler for async
1595 		 * callers, we keep returning 0 until the next message is fully
1596 		 * available, even if it is not Copy Data.
1597 		 */
1598 		conn->inCursor = conn->inStart;
1599 		if (pqGetc(&id, conn))
1600 			return 0;
1601 		if (pqGetInt(&msgLength, 4, conn))
1602 			return 0;
1603 		if (msgLength < 4)
1604 		{
1605 			handleSyncLoss(conn, id, msgLength);
1606 			return -2;
1607 		}
1608 		avail = conn->inEnd - conn->inCursor;
1609 		if (avail < msgLength - 4)
1610 		{
1611 			/*
1612 			 * Before returning, enlarge the input buffer if needed to hold
1613 			 * the whole message.  See notes in parseInput.
1614 			 */
1615 			if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength - 4,
1616 									 conn))
1617 			{
1618 				/*
1619 				 * XXX add some better recovery code... plan is to skip over
1620 				 * the message using its length, then report an error. For the
1621 				 * moment, just treat this like loss of sync (which indeed it
1622 				 * might be!)
1623 				 */
1624 				handleSyncLoss(conn, id, msgLength);
1625 				return -2;
1626 			}
1627 			return 0;
1628 		}
1629 
1630 		/*
1631 		 * If it's a legitimate async message type, process it.  (NOTIFY
1632 		 * messages are not currently possible here, but we handle them for
1633 		 * completeness.)  Otherwise, if it's anything except Copy Data,
1634 		 * report end-of-copy.
1635 		 */
1636 		switch (id)
1637 		{
1638 			case 'A':			/* NOTIFY */
1639 				if (getNotify(conn))
1640 					return 0;
1641 				break;
1642 			case 'N':			/* NOTICE */
1643 				if (pqGetErrorNotice3(conn, false))
1644 					return 0;
1645 				break;
1646 			case 'S':			/* ParameterStatus */
1647 				if (getParameterStatus(conn))
1648 					return 0;
1649 				break;
1650 			case 'd':			/* Copy Data, pass it back to caller */
1651 				return msgLength;
1652 			case 'c':
1653 
1654 				/*
1655 				 * If this is a CopyDone message, exit COPY_OUT mode and let
1656 				 * caller read status with PQgetResult().  If we're in
1657 				 * COPY_BOTH mode, return to COPY_IN mode.
1658 				 */
1659 				if (conn->asyncStatus == PGASYNC_COPY_BOTH)
1660 					conn->asyncStatus = PGASYNC_COPY_IN;
1661 				else
1662 					conn->asyncStatus = PGASYNC_BUSY;
1663 				return -1;
1664 			default:			/* treat as end of copy */
1665 
1666 				/*
1667 				 * Any other message terminates either COPY_IN or COPY_BOTH
1668 				 * mode.
1669 				 */
1670 				conn->asyncStatus = PGASYNC_BUSY;
1671 				return -1;
1672 		}
1673 
1674 		/* trace server-to-client message */
1675 		if (conn->Pfdebug)
1676 			pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
1677 
1678 		/* Drop the processed message and loop around for another */
1679 		conn->inStart = conn->inCursor;
1680 	}
1681 }
1682 
1683 /*
1684  * PQgetCopyData - read a row of data from the backend during COPY OUT
1685  * or COPY BOTH
1686  *
1687  * If successful, sets *buffer to point to a malloc'd row of data, and
1688  * returns row length (always > 0) as result.
1689  * Returns 0 if no row available yet (only possible if async is true),
1690  * -1 if end of copy (consult PQgetResult), or -2 if error (consult
1691  * PQerrorMessage).
1692  */
1693 int
pqGetCopyData3(PGconn * conn,char ** buffer,int async)1694 pqGetCopyData3(PGconn *conn, char **buffer, int async)
1695 {
1696 	int			msgLength;
1697 
1698 	for (;;)
1699 	{
1700 		/*
1701 		 * Collect the next input message.  To make life simpler for async
1702 		 * callers, we keep returning 0 until the next message is fully
1703 		 * available, even if it is not Copy Data.
1704 		 */
1705 		msgLength = getCopyDataMessage(conn);
1706 		if (msgLength < 0)
1707 			return msgLength;	/* end-of-copy or error */
1708 		if (msgLength == 0)
1709 		{
1710 			/* Don't block if async read requested */
1711 			if (async)
1712 				return 0;
1713 			/* Need to load more data */
1714 			if (pqWait(true, false, conn) ||
1715 				pqReadData(conn) < 0)
1716 				return -2;
1717 			continue;
1718 		}
1719 
1720 		/*
1721 		 * Drop zero-length messages (shouldn't happen anyway).  Otherwise
1722 		 * pass the data back to the caller.
1723 		 */
1724 		msgLength -= 4;
1725 		if (msgLength > 0)
1726 		{
1727 			*buffer = (char *) malloc(msgLength + 1);
1728 			if (*buffer == NULL)
1729 			{
1730 				appendPQExpBufferStr(&conn->errorMessage,
1731 									 libpq_gettext("out of memory\n"));
1732 				return -2;
1733 			}
1734 			memcpy(*buffer, &conn->inBuffer[conn->inCursor], msgLength);
1735 			(*buffer)[msgLength] = '\0';	/* Add terminating null */
1736 
1737 			/* Mark message consumed */
1738 			conn->inStart = conn->inCursor + msgLength;
1739 
1740 			return msgLength;
1741 		}
1742 
1743 		/* Empty, so drop it and loop around for another */
1744 		conn->inStart = conn->inCursor;
1745 	}
1746 }
1747 
1748 /*
1749  * PQgetline - gets a newline-terminated string from the backend.
1750  *
1751  * See fe-exec.c for documentation.
1752  */
1753 int
pqGetline3(PGconn * conn,char * s,int maxlen)1754 pqGetline3(PGconn *conn, char *s, int maxlen)
1755 {
1756 	int			status;
1757 
1758 	if (conn->sock == PGINVALID_SOCKET ||
1759 		(conn->asyncStatus != PGASYNC_COPY_OUT &&
1760 		 conn->asyncStatus != PGASYNC_COPY_BOTH) ||
1761 		conn->copy_is_binary)
1762 	{
1763 		appendPQExpBufferStr(&conn->errorMessage,
1764 							 libpq_gettext("PQgetline: not doing text COPY OUT\n"));
1765 		*s = '\0';
1766 		return EOF;
1767 	}
1768 
1769 	while ((status = PQgetlineAsync(conn, s, maxlen - 1)) == 0)
1770 	{
1771 		/* need to load more data */
1772 		if (pqWait(true, false, conn) ||
1773 			pqReadData(conn) < 0)
1774 		{
1775 			*s = '\0';
1776 			return EOF;
1777 		}
1778 	}
1779 
1780 	if (status < 0)
1781 	{
1782 		/* End of copy detected; gin up old-style terminator */
1783 		strcpy(s, "\\.");
1784 		return 0;
1785 	}
1786 
1787 	/* Add null terminator, and strip trailing \n if present */
1788 	if (s[status - 1] == '\n')
1789 	{
1790 		s[status - 1] = '\0';
1791 		return 0;
1792 	}
1793 	else
1794 	{
1795 		s[status] = '\0';
1796 		return 1;
1797 	}
1798 }
1799 
1800 /*
1801  * PQgetlineAsync - gets a COPY data row without blocking.
1802  *
1803  * See fe-exec.c for documentation.
1804  */
1805 int
pqGetlineAsync3(PGconn * conn,char * buffer,int bufsize)1806 pqGetlineAsync3(PGconn *conn, char *buffer, int bufsize)
1807 {
1808 	int			msgLength;
1809 	int			avail;
1810 
1811 	if (conn->asyncStatus != PGASYNC_COPY_OUT
1812 		&& conn->asyncStatus != PGASYNC_COPY_BOTH)
1813 		return -1;				/* we are not doing a copy... */
1814 
1815 	/*
1816 	 * Recognize the next input message.  To make life simpler for async
1817 	 * callers, we keep returning 0 until the next message is fully available
1818 	 * even if it is not Copy Data.  This should keep PQendcopy from blocking.
1819 	 * (Note: unlike pqGetCopyData3, we do not change asyncStatus here.)
1820 	 */
1821 	msgLength = getCopyDataMessage(conn);
1822 	if (msgLength < 0)
1823 		return -1;				/* end-of-copy or error */
1824 	if (msgLength == 0)
1825 		return 0;				/* no data yet */
1826 
1827 	/*
1828 	 * Move data from libpq's buffer to the caller's.  In the case where a
1829 	 * prior call found the caller's buffer too small, we use
1830 	 * conn->copy_already_done to remember how much of the row was already
1831 	 * returned to the caller.
1832 	 */
1833 	conn->inCursor += conn->copy_already_done;
1834 	avail = msgLength - 4 - conn->copy_already_done;
1835 	if (avail <= bufsize)
1836 	{
1837 		/* Able to consume the whole message */
1838 		memcpy(buffer, &conn->inBuffer[conn->inCursor], avail);
1839 		/* Mark message consumed */
1840 		conn->inStart = conn->inCursor + avail;
1841 		/* Reset state for next time */
1842 		conn->copy_already_done = 0;
1843 		return avail;
1844 	}
1845 	else
1846 	{
1847 		/* We must return a partial message */
1848 		memcpy(buffer, &conn->inBuffer[conn->inCursor], bufsize);
1849 		/* The message is NOT consumed from libpq's buffer */
1850 		conn->copy_already_done += bufsize;
1851 		return bufsize;
1852 	}
1853 }
1854 
1855 /*
1856  * PQendcopy
1857  *
1858  * See fe-exec.c for documentation.
1859  */
1860 int
pqEndcopy3(PGconn * conn)1861 pqEndcopy3(PGconn *conn)
1862 {
1863 	PGresult   *result;
1864 
1865 	if (conn->asyncStatus != PGASYNC_COPY_IN &&
1866 		conn->asyncStatus != PGASYNC_COPY_OUT &&
1867 		conn->asyncStatus != PGASYNC_COPY_BOTH)
1868 	{
1869 		appendPQExpBufferStr(&conn->errorMessage,
1870 							 libpq_gettext("no COPY in progress\n"));
1871 		return 1;
1872 	}
1873 
1874 	/* Send the CopyDone message if needed */
1875 	if (conn->asyncStatus == PGASYNC_COPY_IN ||
1876 		conn->asyncStatus == PGASYNC_COPY_BOTH)
1877 	{
1878 		if (pqPutMsgStart('c', conn) < 0 ||
1879 			pqPutMsgEnd(conn) < 0)
1880 			return 1;
1881 
1882 		/*
1883 		 * If we sent the COPY command in extended-query mode, we must issue a
1884 		 * Sync as well.
1885 		 */
1886 		if (conn->cmd_queue_head &&
1887 			conn->cmd_queue_head->queryclass != PGQUERY_SIMPLE)
1888 		{
1889 			if (pqPutMsgStart('S', conn) < 0 ||
1890 				pqPutMsgEnd(conn) < 0)
1891 				return 1;
1892 		}
1893 	}
1894 
1895 	/*
1896 	 * make sure no data is waiting to be sent, abort if we are non-blocking
1897 	 * and the flush fails
1898 	 */
1899 	if (pqFlush(conn) && pqIsnonblocking(conn))
1900 		return 1;
1901 
1902 	/* Return to active duty */
1903 	conn->asyncStatus = PGASYNC_BUSY;
1904 
1905 	/*
1906 	 * Non blocking connections may have to abort at this point.  If everyone
1907 	 * played the game there should be no problem, but in error scenarios the
1908 	 * expected messages may not have arrived yet.  (We are assuming that the
1909 	 * backend's packetizing will ensure that CommandComplete arrives along
1910 	 * with the CopyDone; are there corner cases where that doesn't happen?)
1911 	 */
1912 	if (pqIsnonblocking(conn) && PQisBusy(conn))
1913 		return 1;
1914 
1915 	/* Wait for the completion response */
1916 	result = PQgetResult(conn);
1917 
1918 	/* Expecting a successful result */
1919 	if (result && result->resultStatus == PGRES_COMMAND_OK)
1920 	{
1921 		PQclear(result);
1922 		return 0;
1923 	}
1924 
1925 	/*
1926 	 * Trouble. For backwards-compatibility reasons, we issue the error
1927 	 * message as if it were a notice (would be nice to get rid of this
1928 	 * silliness, but too many apps probably don't handle errors from
1929 	 * PQendcopy reasonably).  Note that the app can still obtain the error
1930 	 * status from the PGconn object.
1931 	 */
1932 	if (conn->errorMessage.len > 0)
1933 	{
1934 		/* We have to strip the trailing newline ... pain in neck... */
1935 		char		svLast = conn->errorMessage.data[conn->errorMessage.len - 1];
1936 
1937 		if (svLast == '\n')
1938 			conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
1939 		pqInternalNotice(&conn->noticeHooks, "%s", conn->errorMessage.data);
1940 		conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;
1941 	}
1942 
1943 	PQclear(result);
1944 
1945 	return 1;
1946 }
1947 
1948 
1949 /*
1950  * PQfn - Send a function call to the POSTGRES backend.
1951  *
1952  * See fe-exec.c for documentation.
1953  */
1954 PGresult *
pqFunctionCall3(PGconn * conn,Oid fnid,int * result_buf,int * actual_result_len,int result_is_int,const PQArgBlock * args,int nargs)1955 pqFunctionCall3(PGconn *conn, Oid fnid,
1956 				int *result_buf, int *actual_result_len,
1957 				int result_is_int,
1958 				const PQArgBlock *args, int nargs)
1959 {
1960 	bool		needInput = false;
1961 	ExecStatusType status = PGRES_FATAL_ERROR;
1962 	char		id;
1963 	int			msgLength;
1964 	int			avail;
1965 	int			i;
1966 
1967 	/* already validated by PQfn */
1968 	Assert(conn->pipelineStatus == PQ_PIPELINE_OFF);
1969 
1970 	/* PQfn already validated connection state */
1971 
1972 	if (pqPutMsgStart('F', conn) < 0 || /* function call msg */
1973 		pqPutInt(fnid, 4, conn) < 0 ||	/* function id */
1974 		pqPutInt(1, 2, conn) < 0 || /* # of format codes */
1975 		pqPutInt(1, 2, conn) < 0 || /* format code: BINARY */
1976 		pqPutInt(nargs, 2, conn) < 0)	/* # of args */
1977 	{
1978 		/* error message should be set up already */
1979 		return NULL;
1980 	}
1981 
1982 	for (i = 0; i < nargs; ++i)
1983 	{							/* len.int4 + contents	   */
1984 		if (pqPutInt(args[i].len, 4, conn))
1985 			return NULL;
1986 		if (args[i].len == -1)
1987 			continue;			/* it's NULL */
1988 
1989 		if (args[i].isint)
1990 		{
1991 			if (pqPutInt(args[i].u.integer, args[i].len, conn))
1992 				return NULL;
1993 		}
1994 		else
1995 		{
1996 			if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
1997 				return NULL;
1998 		}
1999 	}
2000 
2001 	if (pqPutInt(1, 2, conn) < 0)	/* result format code: BINARY */
2002 		return NULL;
2003 
2004 	if (pqPutMsgEnd(conn) < 0 ||
2005 		pqFlush(conn))
2006 		return NULL;
2007 
2008 	for (;;)
2009 	{
2010 		if (needInput)
2011 		{
2012 			/* Wait for some data to arrive (or for the channel to close) */
2013 			if (pqWait(true, false, conn) ||
2014 				pqReadData(conn) < 0)
2015 				break;
2016 		}
2017 
2018 		/*
2019 		 * Scan the message. If we run out of data, loop around to try again.
2020 		 */
2021 		needInput = true;
2022 
2023 		conn->inCursor = conn->inStart;
2024 		if (pqGetc(&id, conn))
2025 			continue;
2026 		if (pqGetInt(&msgLength, 4, conn))
2027 			continue;
2028 
2029 		/*
2030 		 * Try to validate message type/length here.  A length less than 4 is
2031 		 * definitely broken.  Large lengths should only be believed for a few
2032 		 * message types.
2033 		 */
2034 		if (msgLength < 4)
2035 		{
2036 			handleSyncLoss(conn, id, msgLength);
2037 			break;
2038 		}
2039 		if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
2040 		{
2041 			handleSyncLoss(conn, id, msgLength);
2042 			break;
2043 		}
2044 
2045 		/*
2046 		 * Can't process if message body isn't all here yet.
2047 		 */
2048 		msgLength -= 4;
2049 		avail = conn->inEnd - conn->inCursor;
2050 		if (avail < msgLength)
2051 		{
2052 			/*
2053 			 * Before looping, enlarge the input buffer if needed to hold the
2054 			 * whole message.  See notes in parseInput.
2055 			 */
2056 			if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
2057 									 conn))
2058 			{
2059 				/*
2060 				 * XXX add some better recovery code... plan is to skip over
2061 				 * the message using its length, then report an error. For the
2062 				 * moment, just treat this like loss of sync (which indeed it
2063 				 * might be!)
2064 				 */
2065 				handleSyncLoss(conn, id, msgLength);
2066 				break;
2067 			}
2068 			continue;
2069 		}
2070 
2071 		/*
2072 		 * We should see V or E response to the command, but might get N
2073 		 * and/or A notices first. We also need to swallow the final Z before
2074 		 * returning.
2075 		 */
2076 		switch (id)
2077 		{
2078 			case 'V':			/* function result */
2079 				if (pqGetInt(actual_result_len, 4, conn))
2080 					continue;
2081 				if (*actual_result_len != -1)
2082 				{
2083 					if (result_is_int)
2084 					{
2085 						if (pqGetInt(result_buf, *actual_result_len, conn))
2086 							continue;
2087 					}
2088 					else
2089 					{
2090 						if (pqGetnchar((char *) result_buf,
2091 									   *actual_result_len,
2092 									   conn))
2093 							continue;
2094 					}
2095 				}
2096 				/* correctly finished function result message */
2097 				status = PGRES_COMMAND_OK;
2098 				break;
2099 			case 'E':			/* error return */
2100 				if (pqGetErrorNotice3(conn, true))
2101 					continue;
2102 				status = PGRES_FATAL_ERROR;
2103 				break;
2104 			case 'A':			/* notify message */
2105 				/* handle notify and go back to processing return values */
2106 				if (getNotify(conn))
2107 					continue;
2108 				break;
2109 			case 'N':			/* notice */
2110 				/* handle notice and go back to processing return values */
2111 				if (pqGetErrorNotice3(conn, false))
2112 					continue;
2113 				break;
2114 			case 'Z':			/* backend is ready for new query */
2115 				if (getReadyForQuery(conn))
2116 					continue;
2117 				/* consume the message and exit */
2118 				conn->inStart += 5 + msgLength;
2119 				/* if we saved a result object (probably an error), use it */
2120 				if (conn->result)
2121 					return pqPrepareAsyncResult(conn);
2122 				return PQmakeEmptyPGresult(conn, status);
2123 			case 'S':			/* parameter status */
2124 				if (getParameterStatus(conn))
2125 					continue;
2126 				break;
2127 			default:
2128 				/* The backend violates the protocol. */
2129 				appendPQExpBuffer(&conn->errorMessage,
2130 								  libpq_gettext("protocol error: id=0x%x\n"),
2131 								  id);
2132 				pqSaveErrorResult(conn);
2133 				/* trust the specified message length as what to skip */
2134 				conn->inStart += 5 + msgLength;
2135 				return pqPrepareAsyncResult(conn);
2136 		}
2137 
2138 		/* trace server-to-client message */
2139 		if (conn->Pfdebug)
2140 			pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
2141 
2142 		/* Completed this message, keep going */
2143 		/* trust the specified message length as what to skip */
2144 		conn->inStart += 5 + msgLength;
2145 		needInput = false;
2146 	}
2147 
2148 	/*
2149 	 * We fall out of the loop only upon failing to read data.
2150 	 * conn->errorMessage has been set by pqWait or pqReadData. We want to
2151 	 * append it to any already-received error message.
2152 	 */
2153 	pqSaveErrorResult(conn);
2154 	return pqPrepareAsyncResult(conn);
2155 }
2156 
2157 
2158 /*
2159  * Construct startup packet
2160  *
2161  * Returns a malloc'd packet buffer, or NULL if out of memory
2162  */
2163 char *
pqBuildStartupPacket3(PGconn * conn,int * packetlen,const PQEnvironmentOption * options)2164 pqBuildStartupPacket3(PGconn *conn, int *packetlen,
2165 					  const PQEnvironmentOption *options)
2166 {
2167 	char	   *startpacket;
2168 
2169 	*packetlen = build_startup_packet(conn, NULL, options);
2170 	startpacket = (char *) malloc(*packetlen);
2171 	if (!startpacket)
2172 		return NULL;
2173 	*packetlen = build_startup_packet(conn, startpacket, options);
2174 	return startpacket;
2175 }
2176 
2177 /*
2178  * Build a startup packet given a filled-in PGconn structure.
2179  *
2180  * We need to figure out how much space is needed, then fill it in.
2181  * To avoid duplicate logic, this routine is called twice: the first time
2182  * (with packet == NULL) just counts the space needed, the second time
2183  * (with packet == allocated space) fills it in.  Return value is the number
2184  * of bytes used.
2185  */
2186 static int
build_startup_packet(const PGconn * conn,char * packet,const PQEnvironmentOption * options)2187 build_startup_packet(const PGconn *conn, char *packet,
2188 					 const PQEnvironmentOption *options)
2189 {
2190 	int			packet_len = 0;
2191 	const PQEnvironmentOption *next_eo;
2192 	const char *val;
2193 
2194 	/* Protocol version comes first. */
2195 	if (packet)
2196 	{
2197 		ProtocolVersion pv = pg_hton32(conn->pversion);
2198 
2199 		memcpy(packet + packet_len, &pv, sizeof(ProtocolVersion));
2200 	}
2201 	packet_len += sizeof(ProtocolVersion);
2202 
2203 	/* Add user name, database name, options */
2204 
2205 #define ADD_STARTUP_OPTION(optname, optval) \
2206 	do { \
2207 		if (packet) \
2208 			strcpy(packet + packet_len, optname); \
2209 		packet_len += strlen(optname) + 1; \
2210 		if (packet) \
2211 			strcpy(packet + packet_len, optval); \
2212 		packet_len += strlen(optval) + 1; \
2213 	} while(0)
2214 
2215 	if (conn->pguser && conn->pguser[0])
2216 		ADD_STARTUP_OPTION("user", conn->pguser);
2217 	if (conn->dbName && conn->dbName[0])
2218 		ADD_STARTUP_OPTION("database", conn->dbName);
2219 	if (conn->replication && conn->replication[0])
2220 		ADD_STARTUP_OPTION("replication", conn->replication);
2221 	if (conn->pgoptions && conn->pgoptions[0])
2222 		ADD_STARTUP_OPTION("options", conn->pgoptions);
2223 	if (conn->send_appname)
2224 	{
2225 		/* Use appname if present, otherwise use fallback */
2226 		val = conn->appname ? conn->appname : conn->fbappname;
2227 		if (val && val[0])
2228 			ADD_STARTUP_OPTION("application_name", val);
2229 	}
2230 
2231 	if (conn->client_encoding_initial && conn->client_encoding_initial[0])
2232 		ADD_STARTUP_OPTION("client_encoding", conn->client_encoding_initial);
2233 
2234 	/* Add any environment-driven GUC settings needed */
2235 	for (next_eo = options; next_eo->envName; next_eo++)
2236 	{
2237 		if ((val = getenv(next_eo->envName)) != NULL)
2238 		{
2239 			if (pg_strcasecmp(val, "default") != 0)
2240 				ADD_STARTUP_OPTION(next_eo->pgName, val);
2241 		}
2242 	}
2243 
2244 	/* Add trailing terminator */
2245 	if (packet)
2246 		packet[packet_len] = '\0';
2247 	packet_len++;
2248 
2249 	return packet_len;
2250 }
2251