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.
--
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches