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