Skip to content

Commit 063dd37

Browse files
committed
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
1 parent aeb1631 commit 063dd37

File tree

2 files changed

+13
-0
lines changed

2 files changed

+13
-0
lines changed

src/backend/access/common/detoast.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,17 @@ toast_decompress_datum_slice(struct varlena *attr, int32 slicelength)
506506

507507
Assert(VARATT_IS_COMPRESSED(attr));
508508

509+
/*
510+
* Some callers may pass a slicelength that's more than the actual
511+
* decompressed size. If so, just decompress normally. This avoids
512+
* possibly allocating a larger-than-necessary result object, and may be
513+
* faster and/or more robust as well. Notably, some versions of liblz4
514+
* have been seen to give wrong results if passed an output size that is
515+
* more than the data's true decompressed size.
516+
*/
517+
if ((uint32) slicelength >= TOAST_COMPRESS_EXTSIZE(attr))
518+
return toast_decompress_datum(attr);
519+
509520
/*
510521
* Fetch the compression method id stored in the compression header and
511522
* decompress the data slice using the appropriate decompression routine.

src/include/access/toast_internals.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ typedef struct toast_compress_header
3131
* Utilities for manipulation of header information for compressed
3232
* toast entries.
3333
*/
34+
#define TOAST_COMPRESS_EXTSIZE(ptr) \
35+
(((toast_compress_header *) (ptr))->tcinfo & VARLENA_EXTSIZE_MASK)
3436
#define TOAST_COMPRESS_METHOD(ptr) \
3537
(((toast_compress_header *) (ptr))->tcinfo >> VARLENA_EXTSIZE_BITS)
3638

0 commit comments

Comments
 (0)