On Thu, Nov 14, 2019 at 03:27:42PM +0530, Rushabh Lathia wrote:
Today I noticed strange behaviour, consider the following test:

postgres@126111=#create table foo ( a text );
CREATE TABLE
postgres@126111=#insert into foo values ( repeat('PostgreSQL is the
world''s best database and leading by an Open Source Community.', 8000));
INSERT 0 1

postgres@126111=#select substring(a from 639921 for 81) from foo;
substring
-----------

(1 row)


Hmmm. I think the issue is heap_tuple_untoast_attr_slice is using the
wrong way to determine compressed size in the VARATT_IS_EXTERNAL_ONDISK
branch. It does this

    max_size = pglz_maximum_compressed_size(sliceoffset + slicelength,
                                            TOAST_COMPRESS_SIZE(attr));

But for the example you've posted TOAST_COMPRESS_SIZE(attr) returns 10,
which is obviously bogus because the TOAST table contains ~75kB of data.

I think it should be doing this instead:

    max_size = pglz_maximum_compressed_size(sliceoffset + slicelength,
                                            toast_pointer.va_extsize);

At least that fixes it for me.

I wonder if this actually explains the crashes 540f3168091 was supposed
to fix, but it just masked them instead.

regards

--
Tomas Vondra                  http://www.2ndQuadrant.com
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
diff --git a/src/backend/access/common/detoast.c 
b/src/backend/access/common/detoast.c
index 47a03fa98b..b796406239 100644
--- a/src/backend/access/common/detoast.c
+++ b/src/backend/access/common/detoast.c
@@ -233,7 +233,7 @@ heap_tuple_untoast_attr_slice(struct varlena *attr,
                         * of a given length (after decompression).
                         */
                        max_size = pglz_maximum_compressed_size(sliceoffset + 
slicelength,
-                                                                               
                        TOAST_COMPRESS_SIZE(attr));
+                                                                               
                        toast_pointer.va_extsize);
 
                        /*
                         * Fetch enough compressed slices (compressed marker 
will get set

Reply via email to