aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/common
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2021-03-22 14:01:20 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2021-03-22 14:01:20 -0400
commit063dd37ebc7644e8db6419565b50dca019e69e86 (patch)
treeb76475f5aa8f96a3ce81c2e1f34ab671070e06ac /src/backend/access/common
parentaeb1631ed207cef2d80e20f79eb52c72f03bca7d (diff)
downloadpostgresql-063dd37ebc7644e8db6419565b50dca019e69e86.tar.gz
postgresql-063dd37ebc7644e8db6419565b50dca019e69e86.zip
Short-circuit slice requests that are for more than the object's size.
substring(), and perhaps other callers, isn't careful to pass a slice length that is no more than the datum's true size. Since toast_decompress_datum_slice's children will palloc the requested slice length, this can waste memory. Also, close study of the liblz4 documentation suggests that it is dependent on the caller to not ask for more than the correct amount of decompressed data; this squares with observed misbehavior with liblz4 1.8.3. Avoid these problems by switching to the normal full-decompression code path if the slice request is >= datum's decompressed size. Tom Lane and Dilip Kumar Discussion: https://postgr.es/m/507597.1616370729@sss.pgh.pa.us
Diffstat (limited to 'src/backend/access/common')
-rw-r--r--src/backend/access/common/detoast.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/src/backend/access/common/detoast.c b/src/backend/access/common/detoast.c
index a7f7a474782..545a6b8867a 100644
--- a/src/backend/access/common/detoast.c
+++ b/src/backend/access/common/detoast.c
@@ -507,6 +507,17 @@ toast_decompress_datum_slice(struct varlena *attr, int32 slicelength)
Assert(VARATT_IS_COMPRESSED(attr));
/*
+ * Some callers may pass a slicelength that's more than the actual
+ * decompressed size. If so, just decompress normally. This avoids
+ * possibly allocating a larger-than-necessary result object, and may be
+ * faster and/or more robust as well. Notably, some versions of liblz4
+ * have been seen to give wrong results if passed an output size that is
+ * more than the data's true decompressed size.
+ */
+ if ((uint32) slicelength >= TOAST_COMPRESS_EXTSIZE(attr))
+ return toast_decompress_datum(attr);
+
+ /*
* Fetch the compression method id stored in the compression header and
* decompress the data slice using the appropriate decompression routine.
*/