Re: Patch for PGunescapeBytea - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: Patch for PGunescapeBytea
Date
Msg-id 200306120116.h5C1Gnl11144@candle.pha.pa.us
Whole thread Raw
In response to Re: Patch for PGunescapeBytea  (Ben Lamb <pgsql-patches@zurgy.org>)
List pgsql-patches
Patch applied.  Thanks.

---------------------------------------------------------------------------


Ben Lamb wrote:
> Here is a new patch for src/interfaces/libpq/fe-exec.c that incorporates the
> change suggested by Magnus. The patch significantly improves the speed of
> PGunescapeBytea().
>
> Ben.
>
>
> > [snip]
> >
> > I think these lines:
> >
> > buffer = realloc(buffer, buflen);
> > ---
> > if (buffer == NULL)
> >     return NULL;
> > ---
> >
> > are wrong. Shouldn't one do:
> > ---
> > tmpbuf=realloc(buf,...);
> > if (!tmpbuf)
> >     free(buf), return 0;
> > ---
> >
> > to avoid a memory leak?
> >
> > ... just checking ;)
> >
> > Magnus
>

[ Attachment, skipping... ]

>
> ---------------------------(end of broadcast)---------------------------
> TIP 5: Have you checked our extensive FAQ?
>
> http://www.postgresql.org/docs/faqs/FAQ.html

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: src/interfaces/libpq/fe-exec.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/interfaces/libpq/fe-exec.c,v
retrieving revision 1.137
diff -c -c -r1.137 fe-exec.c
*** src/interfaces/libpq/fe-exec.c    8 Jun 2003 17:43:00 -0000    1.137
--- src/interfaces/libpq/fe-exec.c    12 Jun 2003 01:16:16 -0000
***************
*** 1690,1695 ****
--- 1690,1697 ----
      return result;
  }

+ #define VAL(CH) ((CH) - '0')
+
  /*
   *        PQunescapeBytea - converts the null terminated string representation
   *        of a bytea, strtext, into binary, filling a buffer. It returns a
***************
*** 1697,1795 ****
   *        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 reversed:
!  *        '\0' == ASCII  0 == \000
!  *        '\'' == ASCII 39 == \'
!  *        '\\' == ASCII 92 == \\
   *
-  *        States:
-  *        0    normal        0->1->2->3->4
-  *        1    \               1->5
-  *        2    \0               1->6
-  *        3    \00
-  *        4    \000
-  *        5    \'
-  *        6    \\
   */
  unsigned char *
  PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen)
  {
!     size_t        buflen;
!     unsigned char *buffer,
!                *bp;
!     const unsigned char *sp;
!     unsigned int state = 0;

!     if (strtext == NULL)
          return NULL;
!     buflen = strlen(strtext);    /* will shrink, also we discover if
!                                  * strtext */
!     buffer = (unsigned char *) malloc(buflen);    /* isn't NULL terminated */
      if (buffer == NULL)
          return NULL;
!     for (bp = buffer, sp = strtext; *sp != '\0'; bp++, sp++)
      {
!         switch (state)
          {
!             case 0:
!                 if (*sp == '\\')
!                     state = 1;
!                 *bp = *sp;
!                 break;
!             case 1:
!                 if (*sp == '\'')    /* state=5 */
!                 {                /* replace \' with 39 */
!                     bp--;
!                     *bp = '\'';
!                     buflen--;
!                     state = 0;
!                 }
!                 else if (*sp == '\\')    /* state=6 */
!                 {                /* replace \\ with 92 */
!                     bp--;
!                     *bp = '\\';
!                     buflen--;
!                     state = 0;
!                 }
                  else
                  {
!                     if (isdigit(*sp))
!                         state = 2;
!                     else
!                         state = 0;
!                     *bp = *sp;
                  }
                  break;
-             case 2:
-                 if (isdigit(*sp))
-                     state = 3;
-                 else
-                     state = 0;
-                 *bp = *sp;
-                 break;
-             case 3:
-                 if (isdigit(*sp))        /* state=4 */
-                 {
-                     int            v;

!                     bp -= 3;
!                     sscanf(sp - 2, "%03o", &v);
!                     *bp = v;
!                     buflen -= 3;
!                     state = 0;
!                 }
!                 else
!                 {
!                     *bp = *sp;
!                     state = 0;
!                 }
!                 break;
          }
      }
!     buffer = realloc(buffer, buflen);
!     if (buffer == NULL)
!         return NULL;

      *retbuflen = buflen;
!     return buffer;
  }
--- 1699,1762 ----
   *        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)
  {
!     size_t strtextlen, buflen;
!     unsigned char *buffer, *tmpbuf;
!     int i, j, byte;

!     if (strtext == NULL) {
          return NULL;
!     }
!
!     strtextlen = strlen(strtext);    /* will shrink, also we discover if
!                                      * strtext isn't NULL terminated */
!     buffer = (unsigned char *)malloc(strtextlen);
      if (buffer == NULL)
          return NULL;
!
!     for (i = j = buflen = 0; i < strtextlen;)
      {
!         switch (strtext[i])
          {
!             case '\\':
!                 i++;
!                 if (strtext[i] == '\\')
!                     buffer[j++] = strtext[i++];
                  else
                  {
!                     if ((isdigit(strtext[i]))   &&
!                         (isdigit(strtext[i+1])) &&
!                         (isdigit(strtext[i+2])))
!                     {
!                         byte = VAL(strtext[i++]);
!                         byte = (byte << 3) + VAL(strtext[i++]);
!                         buffer[j++] = (byte << 3) + VAL(strtext[i++]);
!                     }
                  }
                  break;

!             default:
!                 buffer[j++] = strtext[i++];
          }
      }
!     buflen = j; /* buflen is the length of the unquoted data */
!     tmpbuf = realloc(buffer, buflen);
!
!     if (!tmpbuf)
!     {
!         free(buffer);
!         return 0;
!     }

      *retbuflen = buflen;
!     return tmpbuf;
  }

pgsql-patches by date:

Previous
From: Josh Berkus
Date:
Subject: Re: [HACKERS] "Adding missing from clause" (replacement)
Next
From: Bruce Momjian
Date:
Subject: Re: pg_autovacuum update