1/*-------------------------------------------------------------------------
2 *
3 * pqformat.c
4 * Routines for formatting and parsing frontend/backend messages
5 *
6 * Outgoing messages are built up in a StringInfo buffer (which is expansible)
7 * and then sent in a single call to pq_putmessage. This module provides data
8 * formatting/conversion routines that are needed to produce valid messages.
9 * Note in particular the distinction between "raw data" and "text"; raw data
10 * is message protocol characters and binary values that are not subject to
11 * character set conversion, while text is converted by character encoding
12 * rules.
13 *
14 * Incoming messages are similarly read into a StringInfo buffer, via
15 * pq_getmessage, and then parsed and converted from that using the routines
16 * in this module.
17 *
18 * These same routines support reading and writing of external binary formats
19 * (typsend/typreceive routines). The conversion routines for individual
20 * data types are exactly the same, only initialization and completion
21 * are different.
22 *
23 *
24 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
25 * Portions Copyright (c) 1994, Regents of the University of California
26 *
27 * src/backend/libpq/pqformat.c
28 *
29 *-------------------------------------------------------------------------
30 */
31/*
32 * INTERFACE ROUTINES
33 * Message assembly and output:
34 * pq_beginmessage - initialize StringInfo buffer
35 * pq_sendbyte - append a raw byte to a StringInfo buffer
36 * pq_sendint - append a binary integer to a StringInfo buffer
37 * pq_sendint64 - append a binary 8-byte int to a StringInfo buffer
38 * pq_sendfloat4 - append a float4 to a StringInfo buffer
39 * pq_sendfloat8 - append a float8 to a StringInfo buffer
40 * pq_sendbytes - append raw data to a StringInfo buffer
41 * pq_sendcountedtext - append a counted text string (with character set conversion)
42 * pq_sendtext - append a text string (with conversion)
43 * pq_sendstring - append a null-terminated text string (with conversion)
44 * pq_send_ascii_string - append a null-terminated text string (without conversion)
45 * pq_endmessage - send the completed message to the frontend
46 * Note: it is also possible to append data to the StringInfo buffer using
47 * the regular StringInfo routines, but this is discouraged since required
48 * character set conversion may not occur.
49 *
50 * typsend support (construct a bytea value containing external binary data):
51 * pq_begintypsend - initialize StringInfo buffer
52 * pq_endtypsend - return the completed string as a "bytea*"
53 *
54 * Special-case message output:
55 * pq_puttextmessage - generate a character set-converted message in one step
56 * pq_putemptymessage - convenience routine for message with empty body
57 *
58 * Message parsing after input:
59 * pq_getmsgbyte - get a raw byte from a message buffer
60 * pq_getmsgint - get a binary integer from a message buffer
61 * pq_getmsgint64 - get a binary 8-byte int from a message buffer
62 * pq_getmsgfloat4 - get a float4 from a message buffer
63 * pq_getmsgfloat8 - get a float8 from a message buffer
64 * pq_getmsgbytes - get raw data from a message buffer
65 * pq_copymsgbytes - copy raw data from a message buffer
66 * pq_getmsgtext - get a counted text string (with conversion)
67 * pq_getmsgstring - get a null-terminated text string (with conversion)
68 * pq_getmsgrawstring - get a null-terminated text string - NO conversion
69 * pq_getmsgend - verify message fully consumed
70 */
71
72#include "postgres.h"
73
74#include <sys/param.h>
75
76#include "libpq/libpq.h"
77#include "libpq/pqformat.h"
78#include "mb/pg_wchar.h"
79#include "port/pg_bswap.h"
80
81
82/* --------------------------------
83 * pq_beginmessage - initialize for sending a message
84 * --------------------------------
85 */
86void
87pq_beginmessage(StringInfo buf, char msgtype)
88{
89 initStringInfo(buf);
90
91 /*
92 * We stash the message type into the buffer's cursor field, expecting
93 * that the pq_sendXXX routines won't touch it. We could alternatively
94 * make it the first byte of the buffer contents, but this seems easier.
95 */
96 buf->cursor = msgtype;
97}
98
99/* --------------------------------
100
101 * pq_beginmessage_reuse - initialize for sending a message, reuse buffer
102 *
103 * This requires the buffer to be allocated in a sufficiently long-lived
104 * memory context.
105 * --------------------------------
106 */
107void
108pq_beginmessage_reuse(StringInfo buf, char msgtype)
109{
110 resetStringInfo(buf);
111
112 /*
113 * We stash the message type into the buffer's cursor field, expecting
114 * that the pq_sendXXX routines won't touch it. We could alternatively
115 * make it the first byte of the buffer contents, but this seems easier.
116 */
117 buf->cursor = msgtype;
118}
119
120/* --------------------------------
121 * pq_sendbytes - append raw data to a StringInfo buffer
122 * --------------------------------
123 */
124void
125pq_sendbytes(StringInfo buf, const char *data, int datalen)
126{
127 /* use variant that maintains a trailing null-byte, out of caution */
128 appendBinaryStringInfo(buf, data, datalen);
129}
130
131/* --------------------------------
132 * pq_sendcountedtext - append a counted text string (with character set conversion)
133 *
134 * The data sent to the frontend by this routine is a 4-byte count field
135 * followed by the string. The count includes itself or not, as per the
136 * countincludesself flag (pre-3.0 protocol requires it to include itself).
137 * The passed text string need not be null-terminated, and the data sent
138 * to the frontend isn't either.
139 * --------------------------------
140 */
141void
142pq_sendcountedtext(StringInfo buf, const char *str, int slen,
143 bool countincludesself)
144{
145 int extra = countincludesself ? 4 : 0;
146 char *p;
147
148 p = pg_server_to_client(str, slen);
149 if (p != str) /* actual conversion has been done? */
150 {
151 slen = strlen(p);
152 pq_sendint32(buf, slen + extra);
153 appendBinaryStringInfoNT(buf, p, slen);
154 pfree(p);
155 }
156 else
157 {
158 pq_sendint32(buf, slen + extra);
159 appendBinaryStringInfoNT(buf, str, slen);
160 }
161}
162
163/* --------------------------------
164 * pq_sendtext - append a text string (with conversion)
165 *
166 * The passed text string need not be null-terminated, and the data sent
167 * to the frontend isn't either. Note that this is not actually useful
168 * for direct frontend transmissions, since there'd be no way for the
169 * frontend to determine the string length. But it is useful for binary
170 * format conversions.
171 * --------------------------------
172 */
173void
174pq_sendtext(StringInfo buf, const char *str, int slen)
175{
176 char *p;
177
178 p = pg_server_to_client(str, slen);
179 if (p != str) /* actual conversion has been done? */
180 {
181 slen = strlen(p);
182 appendBinaryStringInfo(buf, p, slen);
183 pfree(p);
184 }
185 else
186 appendBinaryStringInfo(buf, str, slen);
187}
188
189/* --------------------------------
190 * pq_sendstring - append a null-terminated text string (with conversion)
191 *
192 * NB: passed text string must be null-terminated, and so is the data
193 * sent to the frontend.
194 * --------------------------------
195 */
196void
197pq_sendstring(StringInfo buf, const char *str)
198{
199 int slen = strlen(str);
200 char *p;
201
202 p = pg_server_to_client(str, slen);
203 if (p != str) /* actual conversion has been done? */
204 {
205 slen = strlen(p);
206 appendBinaryStringInfoNT(buf, p, slen + 1);
207 pfree(p);
208 }
209 else
210 appendBinaryStringInfoNT(buf, str, slen + 1);
211}
212
213/* --------------------------------
214 * pq_send_ascii_string - append a null-terminated text string (without conversion)
215 *
216 * This function intentionally bypasses encoding conversion, instead just
217 * silently replacing any non-7-bit-ASCII characters with question marks.
218 * It is used only when we are having trouble sending an error message to
219 * the client with normal localization and encoding conversion. The caller
220 * should already have taken measures to ensure the string is just ASCII;
221 * the extra work here is just to make certain we don't send a badly encoded
222 * string to the client (which might or might not be robust about that).
223 *
224 * NB: passed text string must be null-terminated, and so is the data
225 * sent to the frontend.
226 * --------------------------------
227 */
228void
229pq_send_ascii_string(StringInfo buf, const char *str)
230{
231 while (*str)
232 {
233 char ch = *str++;
234
235 if (IS_HIGHBIT_SET(ch))
236 ch = '?';
237 appendStringInfoCharMacro(buf, ch);
238 }
239 appendStringInfoChar(buf, '\0');
240}
241
242/* --------------------------------
243 * pq_sendfloat4 - append a float4 to a StringInfo buffer
244 *
245 * The point of this routine is to localize knowledge of the external binary
246 * representation of float4, which is a component of several datatypes.
247 *
248 * We currently assume that float4 should be byte-swapped in the same way
249 * as int4. This rule is not perfect but it gives us portability across
250 * most IEEE-float-using architectures.
251 * --------------------------------
252 */
253void
254pq_sendfloat4(StringInfo buf, float4 f)
255{
256 union
257 {
258 float4 f;
259 uint32 i;
260 } swap;
261
262 swap.f = f;
263 pq_sendint32(buf, swap.i);
264}
265
266/* --------------------------------
267 * pq_sendfloat8 - append a float8 to a StringInfo buffer
268 *
269 * The point of this routine is to localize knowledge of the external binary
270 * representation of float8, which is a component of several datatypes.
271 *
272 * We currently assume that float8 should be byte-swapped in the same way
273 * as int8. This rule is not perfect but it gives us portability across
274 * most IEEE-float-using architectures.
275 * --------------------------------
276 */
277void
278pq_sendfloat8(StringInfo buf, float8 f)
279{
280 union
281 {
282 float8 f;
283 int64 i;
284 } swap;
285
286 swap.f = f;
287 pq_sendint64(buf, swap.i);
288}
289
290/* --------------------------------
291 * pq_endmessage - send the completed message to the frontend
292 *
293 * The data buffer is pfree()d, but if the StringInfo was allocated with
294 * makeStringInfo then the caller must still pfree it.
295 * --------------------------------
296 */
297void
298pq_endmessage(StringInfo buf)
299{
300 /* msgtype was saved in cursor field */
301 (void) pq_putmessage(buf->cursor, buf->data, buf->len);
302 /* no need to complain about any failure, since pqcomm.c already did */
303 pfree(buf->data);
304 buf->data = NULL;
305}
306
307/* --------------------------------
308 * pq_endmessage_reuse - send the completed message to the frontend
309 *
310 * The data buffer is *not* freed, allowing to reuse the buffer with
311 * pq_beginmessage_reuse.
312 --------------------------------
313 */
314
315void
316pq_endmessage_reuse(StringInfo buf)
317{
318 /* msgtype was saved in cursor field */
319 (void) pq_putmessage(buf->cursor, buf->data, buf->len);
320}
321
322
323/* --------------------------------
324 * pq_begintypsend - initialize for constructing a bytea result
325 * --------------------------------
326 */
327void
328pq_begintypsend(StringInfo buf)
329{
330 initStringInfo(buf);
331 /* Reserve four bytes for the bytea length word */
332 appendStringInfoCharMacro(buf, '\0');
333 appendStringInfoCharMacro(buf, '\0');
334 appendStringInfoCharMacro(buf, '\0');
335 appendStringInfoCharMacro(buf, '\0');
336}
337
338/* --------------------------------
339 * pq_endtypsend - finish constructing a bytea result
340 *
341 * The data buffer is returned as the palloc'd bytea value. (We expect
342 * that it will be suitably aligned for this because it has been palloc'd.)
343 * We assume the StringInfoData is just a local variable in the caller and
344 * need not be pfree'd.
345 * --------------------------------
346 */
347bytea *
348pq_endtypsend(StringInfo buf)
349{
350 bytea *result = (bytea *) buf->data;
351
352 /* Insert correct length into bytea length word */
353 Assert(buf->len >= VARHDRSZ);
354 SET_VARSIZE(result, buf->len);
355
356 return result;
357}
358
359
360/* --------------------------------
361 * pq_puttextmessage - generate a character set-converted message in one step
362 *
363 * This is the same as the pqcomm.c routine pq_putmessage, except that
364 * the message body is a null-terminated string to which encoding
365 * conversion applies.
366 * --------------------------------
367 */
368void
369pq_puttextmessage(char msgtype, const char *str)
370{
371 int slen = strlen(str);
372 char *p;
373
374 p = pg_server_to_client(str, slen);
375 if (p != str) /* actual conversion has been done? */
376 {
377 (void) pq_putmessage(msgtype, p, strlen(p) + 1);
378 pfree(p);
379 return;
380 }
381 (void) pq_putmessage(msgtype, str, slen + 1);
382}
383
384
385/* --------------------------------
386 * pq_putemptymessage - convenience routine for message with empty body
387 * --------------------------------
388 */
389void
390pq_putemptymessage(char msgtype)
391{
392 (void) pq_putmessage(msgtype, NULL, 0);
393}
394
395
396/* --------------------------------
397 * pq_getmsgbyte - get a raw byte from a message buffer
398 * --------------------------------
399 */
400int
401pq_getmsgbyte(StringInfo msg)
402{
403 if (msg->cursor >= msg->len)
404 ereport(ERROR,
405 (errcode(ERRCODE_PROTOCOL_VIOLATION),
406 errmsg("no data left in message")));
407 return (unsigned char) msg->data[msg->cursor++];
408}
409
410/* --------------------------------
411 * pq_getmsgint - get a binary integer from a message buffer
412 *
413 * Values are treated as unsigned.
414 * --------------------------------
415 */
416unsigned int
417pq_getmsgint(StringInfo msg, int b)
418{
419 unsigned int result;
420 unsigned char n8;
421 uint16 n16;
422 uint32 n32;
423
424 switch (b)
425 {
426 case 1:
427 pq_copymsgbytes(msg, (char *) &n8, 1);
428 result = n8;
429 break;
430 case 2:
431 pq_copymsgbytes(msg, (char *) &n16, 2);
432 result = pg_ntoh16(n16);
433 break;
434 case 4:
435 pq_copymsgbytes(msg, (char *) &n32, 4);
436 result = pg_ntoh32(n32);
437 break;
438 default:
439 elog(ERROR, "unsupported integer size %d", b);
440 result = 0; /* keep compiler quiet */
441 break;
442 }
443 return result;
444}
445
446/* --------------------------------
447 * pq_getmsgint64 - get a binary 8-byte int from a message buffer
448 *
449 * It is tempting to merge this with pq_getmsgint, but we'd have to make the
450 * result int64 for all data widths --- that could be a big performance
451 * hit on machines where int64 isn't efficient.
452 * --------------------------------
453 */
454int64
455pq_getmsgint64(StringInfo msg)
456{
457 uint64 n64;
458
459 pq_copymsgbytes(msg, (char *) &n64, sizeof(n64));
460
461 return pg_ntoh64(n64);
462}
463
464/* --------------------------------
465 * pq_getmsgfloat4 - get a float4 from a message buffer
466 *
467 * See notes for pq_sendfloat4.
468 * --------------------------------
469 */
470float4
471pq_getmsgfloat4(StringInfo msg)
472{
473 union
474 {
475 float4 f;
476 uint32 i;
477 } swap;
478
479 swap.i = pq_getmsgint(msg, 4);
480 return swap.f;
481}
482
483/* --------------------------------
484 * pq_getmsgfloat8 - get a float8 from a message buffer
485 *
486 * See notes for pq_sendfloat8.
487 * --------------------------------
488 */
489float8
490pq_getmsgfloat8(StringInfo msg)
491{
492 union
493 {
494 float8 f;
495 int64 i;
496 } swap;
497
498 swap.i = pq_getmsgint64(msg);
499 return swap.f;
500}
501
502/* --------------------------------
503 * pq_getmsgbytes - get raw data from a message buffer
504 *
505 * Returns a pointer directly into the message buffer; note this
506 * may not have any particular alignment.
507 * --------------------------------
508 */
509const char *
510pq_getmsgbytes(StringInfo msg, int datalen)
511{
512 const char *result;
513
514 if (datalen < 0 || datalen > (msg->len - msg->cursor))
515 ereport(ERROR,
516 (errcode(ERRCODE_PROTOCOL_VIOLATION),
517 errmsg("insufficient data left in message")));
518 result = &msg->data[msg->cursor];
519 msg->cursor += datalen;
520 return result;
521}
522
523/* --------------------------------
524 * pq_copymsgbytes - copy raw data from a message buffer
525 *
526 * Same as above, except data is copied to caller's buffer.
527 * --------------------------------
528 */
529void
530pq_copymsgbytes(StringInfo msg, char *buf, int datalen)
531{
532 if (datalen < 0 || datalen > (msg->len - msg->cursor))
533 ereport(ERROR,
534 (errcode(ERRCODE_PROTOCOL_VIOLATION),
535 errmsg("insufficient data left in message")));
536 memcpy(buf, &msg->data[msg->cursor], datalen);
537 msg->cursor += datalen;
538}
539
540/* --------------------------------
541 * pq_getmsgtext - get a counted text string (with conversion)
542 *
543 * Always returns a pointer to a freshly palloc'd result.
544 * The result has a trailing null, *and* we return its strlen in *nbytes.
545 * --------------------------------
546 */
547char *
548pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
549{
550 char *str;
551 char *p;
552
553 if (rawbytes < 0 || rawbytes > (msg->len - msg->cursor))
554 ereport(ERROR,
555 (errcode(ERRCODE_PROTOCOL_VIOLATION),
556 errmsg("insufficient data left in message")));
557 str = &msg->data[msg->cursor];
558 msg->cursor += rawbytes;
559
560 p = pg_client_to_server(str, rawbytes);
561 if (p != str) /* actual conversion has been done? */
562 *nbytes = strlen(p);
563 else
564 {
565 p = (char *) palloc(rawbytes + 1);
566 memcpy(p, str, rawbytes);
567 p[rawbytes] = '\0';
568 *nbytes = rawbytes;
569 }
570 return p;
571}
572
573/* --------------------------------
574 * pq_getmsgstring - get a null-terminated text string (with conversion)
575 *
576 * May return a pointer directly into the message buffer, or a pointer
577 * to a palloc'd conversion result.
578 * --------------------------------
579 */
580const char *
581pq_getmsgstring(StringInfo msg)
582{
583 char *str;
584 int slen;
585
586 str = &msg->data[msg->cursor];
587
588 /*
589 * It's safe to use strlen() here because a StringInfo is guaranteed to
590 * have a trailing null byte. But check we found a null inside the
591 * message.
592 */
593 slen = strlen(str);
594 if (msg->cursor + slen >= msg->len)
595 ereport(ERROR,
596 (errcode(ERRCODE_PROTOCOL_VIOLATION),
597 errmsg("invalid string in message")));
598 msg->cursor += slen + 1;
599
600 return pg_client_to_server(str, slen);
601}
602
603/* --------------------------------
604 * pq_getmsgrawstring - get a null-terminated text string - NO conversion
605 *
606 * Returns a pointer directly into the message buffer.
607 * --------------------------------
608 */
609const char *
610pq_getmsgrawstring(StringInfo msg)
611{
612 char *str;
613 int slen;
614
615 str = &msg->data[msg->cursor];
616
617 /*
618 * It's safe to use strlen() here because a StringInfo is guaranteed to
619 * have a trailing null byte. But check we found a null inside the
620 * message.
621 */
622 slen = strlen(str);
623 if (msg->cursor + slen >= msg->len)
624 ereport(ERROR,
625 (errcode(ERRCODE_PROTOCOL_VIOLATION),
626 errmsg("invalid string in message")));
627 msg->cursor += slen + 1;
628
629 return str;
630}
631
632/* --------------------------------
633 * pq_getmsgend - verify message fully consumed
634 * --------------------------------
635 */
636void
637pq_getmsgend(StringInfo msg)
638{
639 if (msg->cursor != msg->len)
640 ereport(ERROR,
641 (errcode(ERRCODE_PROTOCOL_VIOLATION),
642 errmsg("invalid message format")));
643}
644