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-2020, 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 */ 86 void 87 pq_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 */ 107 void 108 pq_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 */ 124 void 125 pq_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 */ 141 void 142 pq_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 */ 173 void 174 pq_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 */ 196 void 197 pq_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 */ 228 void 229 pq_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 */ 253 void 254 pq_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 */ 277 void 278 pq_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 */ 297 void 298 pq_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 315 void 316 pq_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 */ 327 void 328 pq_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 */ 347 bytea * 348 pq_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 */ 368 void 369 pq_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 */ 389 void 390 pq_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 */ 400 int 401 pq_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 */ 416 unsigned int 417 pq_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 */ 454 int64 455 pq_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 */ 470 float4 471 pq_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 */ 489 float8 490 pq_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 */ 509 const char * 510 pq_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 */ 529 void 530 pq_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 */ 547 char * 548 pq_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 */ 580 const char * 581 pq_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 */ 609 const char * 610 pq_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 */ 636 void 637 pq_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