Skip to content

Commit fe578cb

Browse files
committed
Fix datumSerialize infrastructure to not crash on non-varlena data.
Commit 1efc7e5 did a poor job of emulating existing logic for touching Datums that might be expanded-object pointers. It didn't check for typlen being -1 first, which meant it could crash on fixed-length pass-by-ref values, and probably on cstring values as well. It also didn't use DatumGetPointer before VARATT_IS_EXTERNAL_EXPANDED, which while currently harmless is not according to documentation nor prevailing style. I also think the lack of any explanation as to why datumSerialize makes these particular nonobvious choices is pretty awful, so fix that. Per report from Jarred Ward. Back-patch to 9.6 where this code came in. Discussion: https://postgr.es/m/6F61E6D2-2F5E-4794-9479-A429BE1CEA4B@simple.com
1 parent 1924ef4 commit fe578cb

File tree

1 file changed

+13
-5
lines changed

1 file changed

+13
-5
lines changed

src/backend/utils/adt/datum.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -264,11 +264,11 @@ datumEstimateSpace(Datum value, bool isnull, bool typByVal, int typLen)
264264
/* no need to use add_size, can't overflow */
265265
if (typByVal)
266266
sz += sizeof(Datum);
267-
else if (VARATT_IS_EXTERNAL_EXPANDED(value))
267+
else if (typLen == -1 &&
268+
VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(value)))
268269
{
269-
ExpandedObjectHeader *eoh = DatumGetEOHP(value);
270-
271-
sz += EOH_get_flat_size(eoh);
270+
/* Expanded objects need to be flattened, see comment below */
271+
sz += EOH_get_flat_size(DatumGetEOHP(value));
272272
}
273273
else
274274
sz += datumGetSize(value, typByVal, typLen);
@@ -282,6 +282,13 @@ datumEstimateSpace(Datum value, bool isnull, bool typByVal, int typLen)
282282
*
283283
* Serialize a possibly-NULL datum into caller-provided storage.
284284
*
285+
* Note: "expanded" objects are flattened so as to produce a self-contained
286+
* representation, but other sorts of toast pointers are transferred as-is.
287+
* This is because the intended use of this function is to pass the value
288+
* to another process within the same database server. The other process
289+
* could not access an "expanded" object within this process's memory, but
290+
* we assume it can dereference the same TOAST pointers this one can.
291+
*
285292
* The format is as follows: first, we write a 4-byte header word, which
286293
* is either the length of a pass-by-reference datum, -1 for a
287294
* pass-by-value datum, or -2 for a NULL. If the value is NULL, nothing
@@ -306,7 +313,8 @@ datumSerialize(Datum value, bool isnull, bool typByVal, int typLen,
306313
header = -2;
307314
else if (typByVal)
308315
header = -1;
309-
else if (VARATT_IS_EXTERNAL_EXPANDED(value))
316+
else if (typLen == -1 &&
317+
VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(value)))
310318
{
311319
eoh = DatumGetEOHP(value);
312320
header = EOH_get_flat_size(eoh);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy