]> granicus.if.org Git - postgresql/commitdiff
Minor cleanup of PQunescapeBytea(). Avoid unportable assumptions about
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 31 Oct 2003 17:43:10 +0000 (17:43 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 31 Oct 2003 17:43:10 +0000 (17:43 +0000)
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.

src/interfaces/libpq/fe-exec.c

index 1967d7429b44d96ecf2abf05af21ea7c75620f75..d25943ee1114851ae6f49a99ef823d93a0ffae57 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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;
 }
 
-#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
  *             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
  *             argument to the function free(3). It is the reverse of PQescapeBytea.
  *
  *             The following transformations are made:
- *             \'       == ASCII 39 == '
  *             \\       == ASCII 92 == \
  *             \ooo == a byte whose value = ooo (ooo is an octal number)
  *             \x       == x (x is any character not matched by the above transformations)
- *
  */
 unsigned char *
 PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen)
@@ -2349,21 +2349,22 @@ PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen)
                                buflen;
        unsigned char *buffer,
                           *tmpbuf;
-       int                     i,
-                               j,
-                               byte;
+       size_t          i,
+                               j;
 
        if (strtext == NULL)
                return NULL;
 
-       strtextlen = strlen(strtext);           /* will shrink, also we discover
-                                                                                * if strtext isn't NULL
-                                                                                * terminated */
-       buffer = (unsigned char *) malloc(strtextlen);
+       strtextlen = strlen(strtext);
+       /*
+        * Length of input is max length of output, but add one to avoid
+        * unportable malloc(0) if input is zero-length.
+        */
+       buffer = (unsigned char *) malloc(strtextlen + 1);
        if (buffer == NULL)
                return NULL;
 
-       for (i = j = buflen = 0; i < (int)strtextlen;)
+       for (i = j = 0; i < strtextlen; )
        {
                switch (strtext[i])
                {
@@ -2373,26 +2374,38 @@ PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen)
                                        buffer[j++] = strtext[i++];
                                else
                                {
-                                       if ((isdigit(strtext[i])) &&
-                                               (isdigit(strtext[i + 1])) &&
-                                               (isdigit(strtext[i + 2])))
+                                       if ((ISFIRSTOCTDIGIT(strtext[i])) &&
+                                               (ISOCTDIGIT(strtext[i + 1])) &&
+                                               (ISOCTDIGIT(strtext[i + 2])))
                                        {
-                                               byte = VAL(strtext[i++]);
-                                               byte = (byte << 3) + VAL(strtext[i++]);
-                                               buffer[j++] = (byte << 3) + VAL(strtext[i++]);
+                                               int             byte;
+
+                                               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;
 
                        default:
                                buffer[j++] = strtext[i++];
+                               break;
                }
        }
-       buflen = j;                                     /* buflen is the length of the unquoted
+       buflen = j;                                     /* buflen is the length of the dequoted
                                                                 * data */
 
        /* 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... */
        if (!tmpbuf)