~ubuntu-branches/ubuntu/oneiric/postgresql-9.1/oneiric-security

« back to all changes in this revision

Viewing changes to src/backend/libpq/pqformat.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

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