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.
This commit is contained in:
parent
774f57038a
commit
bcf4d35699
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.152 2003/10/19 21:36:41 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.153 2003/10/31 17:43:10 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -2326,21 +2326,21 @@ PQescapeBytea(const unsigned char *bintext, size_t binlen, size_t *bytealen)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define VAL(CH) ((CH) - '0')
|
#define ISFIRSTOCTDIGIT(CH) ((CH) >= '0' && (CH) <= '3')
|
||||||
|
#define ISOCTDIGIT(CH) ((CH) >= '0' && (CH) <= '7')
|
||||||
|
#define OCTVAL(CH) ((CH) - '0')
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PQunescapeBytea - converts the null terminated string representation
|
* PQunescapeBytea - converts the null terminated string representation
|
||||||
* of a bytea, strtext, into binary, filling a buffer. It returns a
|
* of a bytea, strtext, into binary, filling a buffer. It returns a
|
||||||
* pointer to the buffer which is NULL on error, and the size of the
|
* pointer to the buffer (or NULL on error), and the size of the
|
||||||
* buffer in retbuflen. The pointer may subsequently be used as an
|
* buffer in retbuflen. The pointer may subsequently be used as an
|
||||||
* argument to the function free(3). It is the reverse of PQescapeBytea.
|
* argument to the function free(3). It is the reverse of PQescapeBytea.
|
||||||
*
|
*
|
||||||
* The following transformations are made:
|
* The following transformations are made:
|
||||||
* \' == ASCII 39 == '
|
|
||||||
* \\ == ASCII 92 == \
|
* \\ == ASCII 92 == \
|
||||||
* \ooo == a byte whose value = ooo (ooo is an octal number)
|
* \ooo == a byte whose value = ooo (ooo is an octal number)
|
||||||
* \x == x (x is any character not matched by the above transformations)
|
* \x == x (x is any character not matched by the above transformations)
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
unsigned char *
|
unsigned char *
|
||||||
PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen)
|
PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen)
|
||||||
@ -2349,21 +2349,22 @@ PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen)
|
|||||||
buflen;
|
buflen;
|
||||||
unsigned char *buffer,
|
unsigned char *buffer,
|
||||||
*tmpbuf;
|
*tmpbuf;
|
||||||
int i,
|
size_t i,
|
||||||
j,
|
j;
|
||||||
byte;
|
|
||||||
|
|
||||||
if (strtext == NULL)
|
if (strtext == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
strtextlen = strlen(strtext); /* will shrink, also we discover
|
strtextlen = strlen(strtext);
|
||||||
* if strtext isn't NULL
|
/*
|
||||||
* terminated */
|
* Length of input is max length of output, but add one to avoid
|
||||||
buffer = (unsigned char *) malloc(strtextlen);
|
* unportable malloc(0) if input is zero-length.
|
||||||
|
*/
|
||||||
|
buffer = (unsigned char *) malloc(strtextlen + 1);
|
||||||
if (buffer == NULL)
|
if (buffer == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for (i = j = buflen = 0; i < (int)strtextlen;)
|
for (i = j = 0; i < strtextlen; )
|
||||||
{
|
{
|
||||||
switch (strtext[i])
|
switch (strtext[i])
|
||||||
{
|
{
|
||||||
@ -2373,26 +2374,38 @@ PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen)
|
|||||||
buffer[j++] = strtext[i++];
|
buffer[j++] = strtext[i++];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((isdigit(strtext[i])) &&
|
if ((ISFIRSTOCTDIGIT(strtext[i])) &&
|
||||||
(isdigit(strtext[i + 1])) &&
|
(ISOCTDIGIT(strtext[i + 1])) &&
|
||||||
(isdigit(strtext[i + 2])))
|
(ISOCTDIGIT(strtext[i + 2])))
|
||||||
{
|
{
|
||||||
byte = VAL(strtext[i++]);
|
int byte;
|
||||||
byte = (byte << 3) + VAL(strtext[i++]);
|
|
||||||
buffer[j++] = (byte << 3) + VAL(strtext[i++]);
|
byte = OCTVAL(strtext[i++]);
|
||||||
|
byte = (byte << 3) + OCTVAL(strtext[i++]);
|
||||||
|
byte = (byte << 3) + OCTVAL(strtext[i++]);
|
||||||
|
buffer[j++] = byte;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Note: if we see '\' followed by something that isn't
|
||||||
|
* a recognized escape sequence, we loop around having
|
||||||
|
* done nothing except advance i. Therefore the something
|
||||||
|
* will be emitted as ordinary data on the next cycle.
|
||||||
|
* Corner case: '\' at end of string will just be discarded.
|
||||||
|
*/
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
buffer[j++] = strtext[i++];
|
buffer[j++] = strtext[i++];
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buflen = j; /* buflen is the length of the unquoted
|
buflen = j; /* buflen is the length of the dequoted
|
||||||
* data */
|
* data */
|
||||||
|
|
||||||
/* Shrink the buffer to be no larger than necessary */
|
/* Shrink the buffer to be no larger than necessary */
|
||||||
tmpbuf = realloc(buffer, buflen);
|
/* +1 avoids unportable behavior when buflen==0 */
|
||||||
|
tmpbuf = realloc(buffer, buflen + 1);
|
||||||
|
|
||||||
/* It would only be a very brain-dead realloc that could fail, but... */
|
/* It would only be a very brain-dead realloc that could fail, but... */
|
||||||
if (!tmpbuf)
|
if (!tmpbuf)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user