pg_lzcompress patch for 8.3, 8.2 branch - Mailing list pgsql-patches

From Zdenek Kotala
Subject pg_lzcompress patch for 8.3, 8.2 branch
Date
Msg-id 483D58FD.9090404@sun.com
Whole thread Raw
Responses Re: pg_lzcompress patch for 8.3, 8.2 branch  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-patches
I attached backported pg_lzcompress patch which is already in head for version
8.2 and 8.3.

Version 8.1 and prior contains more changes in decompress code and they does not
contain any check. Shell I backported it as well or it will be better to keep it
untouched?


        Zdenek
*** src/backend/utils/adt/pg_lzcompress.c    2006/10/05 23:33:33    1.23
--- src/backend/utils/adt/pg_lzcompress.c    2008/03/08 01:09:36    1.31
*************** pglz_compress(const char *source, int32
*** 631,656 ****
  void
  pglz_decompress(const PGLZ_Header *source, char *dest)
  {
!     const unsigned char *dp;
!     const unsigned char *dend;
!     unsigned char *bp;
!     unsigned char ctrl;
!     int32        ctrlc;
!     int32        len;
!     int32        off;
!     int32        destsize;
!
!     dp = ((const unsigned char *) source) + sizeof(PGLZ_Header);
!     dend = ((const unsigned char *) source) + VARATT_SIZE(source);
!     bp = (unsigned char *) dest;

!     while (dp < dend)
      {
          /*
!          * Read one control byte and process the next 8 items.
           */
!         ctrl = *dp++;
!         for (ctrlc = 0; ctrlc < 8 && dp < dend; ctrlc++)
          {
              if (ctrl & 1)
              {
--- 641,666 ----
  void
  pglz_decompress(const PGLZ_Header *source, char *dest)
  {
!     const unsigned char *sp;
!     const unsigned char *srcend;
!     unsigned char *dp;
!     unsigned char *destend;
!
!     sp = ((const unsigned char *) source) + sizeof(PGLZ_Header);
!     srcend = ((const unsigned char *) source) + VARATT_SIZE(source);
!     dp = (unsigned char *) dest;
!     destend = dp + source->rawsize;

!     while (sp < srcend && dp < destend)
      {
          /*
!          * Read one control byte and process the next 8 items (or as many
!          * as remain in the compressed input).
           */
!         unsigned char ctrl = *sp++;
!         int        ctrlc;
!
!         for (ctrlc = 0; ctrlc < 8 && sp < srcend; ctrlc++)
          {
              if (ctrl & 1)
              {
*************** pglz_decompress(const PGLZ_Header *sourc
*** 661,671 ****
                   * coded as 18, another extension tag byte tells how much
                   * longer the match really was (0-255).
                   */
!                 len = (dp[0] & 0x0f) + 3;
!                 off = ((dp[0] & 0xf0) << 4) | dp[1];
!                 dp += 2;
                  if (len == 18)
!                     len += *dp++;

                  /*
                   * Now we copy the bytes specified by the tag from OUTPUT to
--- 671,697 ----
                   * coded as 18, another extension tag byte tells how much
                   * longer the match really was (0-255).
                   */
!                 int32        len;
!                 int32        off;
!
!                 len = (sp[0] & 0x0f) + 3;
!                 off = ((sp[0] & 0xf0) << 4) | sp[1];
!                 sp += 2;
                  if (len == 18)
!                     len += *sp++;
!
!                 /*
!                  * Check for output buffer overrun, to ensure we don't
!                  * clobber memory in case of corrupt input.  Note: we must
!                  * advance dp here to ensure the error is detected below
!                  * the loop.  We don't simply put the elog inside the loop
!                  * since that will probably interfere with optimization.
!                  */
!                 if (dp + len > destend)
!                 {
!                     dp += len;
!                     break;
!                 }

                  /*
                   * Now we copy the bytes specified by the tag from OUTPUT to
*************** pglz_decompress(const PGLZ_Header *sourc
*** 675,682 ****
                   */
                  while (len--)
                  {
!                     *bp = bp[-off];
!                     bp++;
                  }
              }
              else
--- 701,708 ----
                   */
                  while (len--)
                  {
!                     *dp = dp[-off];
!                     dp++;
                  }
              }
              else
*************** pglz_decompress(const PGLZ_Header *sourc
*** 685,691 ****
                   * An unset control bit means LITERAL BYTE. So we just copy
                   * one from INPUT to OUTPUT.
                   */
!                 *bp++ = *dp++;
              }

              /*
--- 711,720 ----
                   * An unset control bit means LITERAL BYTE. So we just copy
                   * one from INPUT to OUTPUT.
                   */
!                 if (dp >= destend)    /* check for buffer overrun */
!                     break;            /* do not clobber memory */
!
!                 *dp++ = *sp++;
              }

              /*
*************** pglz_decompress(const PGLZ_Header *sourc
*** 696,709 ****
      }

      /*
!      * Check we decompressed the right amount, else die.  This is a FATAL
!      * condition if we tromped on more memory than expected (we assume we
!      * have not tromped on shared memory, though, so need not PANIC).
!      */
!     destsize = (char *) bp - dest;
!     if (destsize != source->rawsize)
!         elog(destsize > source->rawsize ? FATAL : ERROR,
!              "compressed data is corrupt");

      /*
       * That's it.
--- 725,734 ----
      }

      /*
!      * Check we decompressed the right amount.
!      */
!     if (dp != destend || sp != srcend)
!         elog(ERROR, "compressed data is corrupt");

      /*
       * That's it.
*** src/backend/utils/adt/pg_lzcompress.c    2008/01/01 19:45:52    1.29
--- src/backend/utils/adt/pg_lzcompress.c    2008/03/08 01:09:36    1.31
*************** pglz_compress(const char *source, int32
*** 631,656 ****
  void
  pglz_decompress(const PGLZ_Header *source, char *dest)
  {
!     const unsigned char *dp;
!     const unsigned char *dend;
!     unsigned char *bp;
!     unsigned char ctrl;
!     int32        ctrlc;
!     int32        len;
!     int32        off;
!     int32        destsize;
!
!     dp = ((const unsigned char *) source) + sizeof(PGLZ_Header);
!     dend = ((const unsigned char *) source) + VARSIZE(source);
!     bp = (unsigned char *) dest;

!     while (dp < dend)
      {
          /*
!          * Read one control byte and process the next 8 items.
           */
!         ctrl = *dp++;
!         for (ctrlc = 0; ctrlc < 8 && dp < dend; ctrlc++)
          {
              if (ctrl & 1)
              {
--- 641,666 ----
  void
  pglz_decompress(const PGLZ_Header *source, char *dest)
  {
!     const unsigned char *sp;
!     const unsigned char *srcend;
!     unsigned char *dp;
!     unsigned char *destend;
!
!     sp = ((const unsigned char *) source) + sizeof(PGLZ_Header);
!     srcend = ((const unsigned char *) source) + VARSIZE(source);
!     dp = (unsigned char *) dest;
!     destend = dp + source->rawsize;

!     while (sp < srcend && dp < destend)
      {
          /*
!          * Read one control byte and process the next 8 items (or as many
!          * as remain in the compressed input).
           */
!         unsigned char ctrl = *sp++;
!         int        ctrlc;
!
!         for (ctrlc = 0; ctrlc < 8 && sp < srcend; ctrlc++)
          {
              if (ctrl & 1)
              {
*************** pglz_decompress(const PGLZ_Header *sourc
*** 661,671 ****
                   * coded as 18, another extension tag byte tells how much
                   * longer the match really was (0-255).
                   */
!                 len = (dp[0] & 0x0f) + 3;
!                 off = ((dp[0] & 0xf0) << 4) | dp[1];
!                 dp += 2;
                  if (len == 18)
!                     len += *dp++;

                  /*
                   * Now we copy the bytes specified by the tag from OUTPUT to
--- 671,697 ----
                   * coded as 18, another extension tag byte tells how much
                   * longer the match really was (0-255).
                   */
!                 int32        len;
!                 int32        off;
!
!                 len = (sp[0] & 0x0f) + 3;
!                 off = ((sp[0] & 0xf0) << 4) | sp[1];
!                 sp += 2;
                  if (len == 18)
!                     len += *sp++;
!
!                 /*
!                  * Check for output buffer overrun, to ensure we don't
!                  * clobber memory in case of corrupt input.  Note: we must
!                  * advance dp here to ensure the error is detected below
!                  * the loop.  We don't simply put the elog inside the loop
!                  * since that will probably interfere with optimization.
!                  */
!                 if (dp + len > destend)
!                 {
!                     dp += len;
!                     break;
!                 }

                  /*
                   * Now we copy the bytes specified by the tag from OUTPUT to
*************** pglz_decompress(const PGLZ_Header *sourc
*** 675,682 ****
                   */
                  while (len--)
                  {
!                     *bp = bp[-off];
!                     bp++;
                  }
              }
              else
--- 701,708 ----
                   */
                  while (len--)
                  {
!                     *dp = dp[-off];
!                     dp++;
                  }
              }
              else
*************** pglz_decompress(const PGLZ_Header *sourc
*** 685,691 ****
                   * An unset control bit means LITERAL BYTE. So we just copy
                   * one from INPUT to OUTPUT.
                   */
!                 *bp++ = *dp++;
              }

              /*
--- 711,720 ----
                   * An unset control bit means LITERAL BYTE. So we just copy
                   * one from INPUT to OUTPUT.
                   */
!                 if (dp >= destend)    /* check for buffer overrun */
!                     break;            /* do not clobber memory */
!
!                 *dp++ = *sp++;
              }

              /*
*************** pglz_decompress(const PGLZ_Header *sourc
*** 696,709 ****
      }

      /*
!      * Check we decompressed the right amount, else die.  This is a FATAL
!      * condition if we tromped on more memory than expected (we assume we have
!      * not tromped on shared memory, though, so need not PANIC).
!      */
!     destsize = (char *) bp - dest;
!     if (destsize != source->rawsize)
!         elog(destsize > source->rawsize ? FATAL : ERROR,
!              "compressed data is corrupt");

      /*
       * That's it.
--- 725,734 ----
      }

      /*
!      * Check we decompressed the right amount.
!      */
!     if (dp != destend || sp != srcend)
!         elog(ERROR, "compressed data is corrupt");

      /*
       * That's it.

pgsql-patches by date:

Previous
From: Magnus Hagander
Date:
Subject: Re: guc config_enum_entry add hidden field
Next
From: Tom Lane
Date:
Subject: Re: pg_lzcompress patch for 8.3, 8.2 branch