aboutsummaryrefslogtreecommitdiff
path: root/src/common/pg_lzcompress.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/pg_lzcompress.c')
-rw-r--r--src/common/pg_lzcompress.c42
1 files changed, 19 insertions, 23 deletions
diff --git a/src/common/pg_lzcompress.c b/src/common/pg_lzcompress.c
index f15725a57c0..97b0e40e403 100644
--- a/src/common/pg_lzcompress.c
+++ b/src/common/pg_lzcompress.c
@@ -29,7 +29,7 @@
*
* int32
* pglz_decompress(const char *source, int32 slen, char *dest,
- * int32 rawsize)
+ * int32 rawsize, bool check_complete)
*
* source is the compressed input.
*
@@ -44,6 +44,12 @@
*
* rawsize is the length of the uncompressed data.
*
+ * check_complete is a flag to let us know if -1 should be
+ * returned in cases where we don't reach the end of the
+ * source or dest buffers, or not. This should be false
+ * if the caller is asking for only a partial result and
+ * true otherwise.
+ *
* The return value is the number of bytes written in the
* buffer dest, or -1 if decompression fails.
*
@@ -674,13 +680,14 @@ pglz_compress(const char *source, int32 slen, char *dest,
* pglz_decompress -
*
* Decompresses source into dest. Returns the number of bytes
- * decompressed in the destination buffer, or -1 if decompression
- * fails.
+ * decompressed in the destination buffer, and *optionally*
+ * checks that both the source and dest buffers have been
+ * fully read and written to, respectively.
* ----------
*/
int32
pglz_decompress(const char *source, int32 slen, char *dest,
- int32 rawsize)
+ int32 rawsize, bool check_complete)
{
const unsigned char *sp;
const unsigned char *srcend;
@@ -701,8 +708,9 @@ pglz_decompress(const char *source, int32 slen, char *dest,
unsigned char ctrl = *sp++;
int ctrlc;
- for (ctrlc = 0; ctrlc < 8 && sp < srcend; ctrlc++)
+ for (ctrlc = 0; ctrlc < 8 && sp < srcend && dp < destend; ctrlc++)
{
+
if (ctrl & 1)
{
/*
@@ -722,24 +730,12 @@ pglz_decompress(const char *source, int32 slen, char *dest,
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
* OUTPUT. It is dangerous and platform dependent to use
* memcpy() here, because the copied areas could overlap
* extremely!
*/
+ len = Min(len, destend - dp);
while (len--)
{
*dp = dp[-off];
@@ -752,9 +748,6 @@ pglz_decompress(const char *source, int32 slen, char *dest,
* 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++;
}
@@ -767,12 +760,15 @@ pglz_decompress(const char *source, int32 slen, char *dest,
/*
* Check we decompressed the right amount.
+ * If we are slicing, then we won't necessarily
+ * be at the end of the source or dest buffers
+ * when we hit a stop, so we don't test them.
*/
- if (dp != destend || sp != srcend)
+ if (check_complete && (dp != destend || sp != srcend))
return -1;
/*
* That's it.
*/
- return rawsize;
+ return (char*)dp - dest;
}