Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit bcf4d35

Browse files
committed
Minor cleanup of PQunescapeBytea(). Avoid unportable assumptions about
behavior of malloc and realloc when request size is 0. Fix escape sequence recognizer so that only valid 3-digit octal sequences are treated as escape sequences ... isdigit() is not a correct test.
1 parent 774f570 commit bcf4d35

File tree

1 file changed

+34
-21
lines changed

1 file changed

+34
-21
lines changed

src/interfaces/libpq/fe-exec.c

+34-21
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.152 2003/10/19 21:36:41 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.153 2003/10/31 17:43:10 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -2326,21 +2326,21 @@ PQescapeBytea(const unsigned char *bintext, size_t binlen, size_t *bytealen)
23262326
return result;
23272327
}
23282328

2329-
#define VAL(CH) ((CH) - '0')
2329+
#define ISFIRSTOCTDIGIT(CH) ((CH) >= '0' && (CH) <= '3')
2330+
#define ISOCTDIGIT(CH) ((CH) >= '0' && (CH) <= '7')
2331+
#define OCTVAL(CH) ((CH) - '0')
23302332

23312333
/*
23322334
* PQunescapeBytea - converts the null terminated string representation
23332335
* of a bytea, strtext, into binary, filling a buffer. It returns a
2334-
* pointer to the buffer which is NULL on error, and the size of the
2336+
* pointer to the buffer (or NULL on error), and the size of the
23352337
* buffer in retbuflen. The pointer may subsequently be used as an
23362338
* argument to the function free(3). It is the reverse of PQescapeBytea.
23372339
*
23382340
* The following transformations are made:
2339-
* \' == ASCII 39 == '
23402341
* \\ == ASCII 92 == \
23412342
* \ooo == a byte whose value = ooo (ooo is an octal number)
23422343
* \x == x (x is any character not matched by the above transformations)
2343-
*
23442344
*/
23452345
unsigned char *
23462346
PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen)
@@ -2349,21 +2349,22 @@ PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen)
23492349
buflen;
23502350
unsigned char *buffer,
23512351
*tmpbuf;
2352-
int i,
2353-
j,
2354-
byte;
2352+
size_t i,
2353+
j;
23552354

23562355
if (strtext == NULL)
23572356
return NULL;
23582357

2359-
strtextlen = strlen(strtext); /* will shrink, also we discover
2360-
* if strtext isn't NULL
2361-
* terminated */
2362-
buffer = (unsigned char *) malloc(strtextlen);
2358+
strtextlen = strlen(strtext);
2359+
/*
2360+
* Length of input is max length of output, but add one to avoid
2361+
* unportable malloc(0) if input is zero-length.
2362+
*/
2363+
buffer = (unsigned char *) malloc(strtextlen + 1);
23632364
if (buffer == NULL)
23642365
return NULL;
23652366

2366-
for (i = j = buflen = 0; i < (int)strtextlen;)
2367+
for (i = j = 0; i < strtextlen; )
23672368
{
23682369
switch (strtext[i])
23692370
{
@@ -2373,26 +2374,38 @@ PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen)
23732374
buffer[j++] = strtext[i++];
23742375
else
23752376
{
2376-
if ((isdigit(strtext[i])) &&
2377-
(isdigit(strtext[i + 1])) &&
2378-
(isdigit(strtext[i + 2])))
2377+
if ((ISFIRSTOCTDIGIT(strtext[i])) &&
2378+
(ISOCTDIGIT(strtext[i + 1])) &&
2379+
(ISOCTDIGIT(strtext[i + 2])))
23792380
{
2380-
byte = VAL(strtext[i++]);
2381-
byte = (byte << 3) + VAL(strtext[i++]);
2382-
buffer[j++] = (byte << 3) + VAL(strtext[i++]);
2381+
int byte;
2382+
2383+
byte = OCTVAL(strtext[i++]);
2384+
byte = (byte << 3) + OCTVAL(strtext[i++]);
2385+
byte = (byte << 3) + OCTVAL(strtext[i++]);
2386+
buffer[j++] = byte;
23832387
}
23842388
}
2389+
/*
2390+
* Note: if we see '\' followed by something that isn't
2391+
* a recognized escape sequence, we loop around having
2392+
* done nothing except advance i. Therefore the something
2393+
* will be emitted as ordinary data on the next cycle.
2394+
* Corner case: '\' at end of string will just be discarded.
2395+
*/
23852396
break;
23862397

23872398
default:
23882399
buffer[j++] = strtext[i++];
2400+
break;
23892401
}
23902402
}
2391-
buflen = j; /* buflen is the length of the unquoted
2403+
buflen = j; /* buflen is the length of the dequoted
23922404
* data */
23932405

23942406
/* Shrink the buffer to be no larger than necessary */
2395-
tmpbuf = realloc(buffer, buflen);
2407+
/* +1 avoids unportable behavior when buflen==0 */
2408+
tmpbuf = realloc(buffer, buflen + 1);
23962409

23972410
/* It would only be a very brain-dead realloc that could fail, but... */
23982411
if (!tmpbuf)

0 commit comments

Comments
 (0)