Skip to content

Commit 9bf4068

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 77d2c00 commit 9bf4068

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
@@ -268,11 +268,11 @@ datumEstimateSpace(Datum value, bool isnull, bool typByVal, int typLen)
268268
/* no need to use add_size, can't overflow */
269269
if (typByVal)
270270
sz += sizeof(Datum);
271-
else if (VARATT_IS_EXTERNAL_EXPANDED(value))
271+
else if (typLen == -1 &&
272+
VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(value)))
272273
{
273-
ExpandedObjectHeader *eoh = DatumGetEOHP(value);
274-
275-
sz += EOH_get_flat_size(eoh);
274+
/* Expanded objects need to be flattened, see comment below */
275+
sz += EOH_get_flat_size(DatumGetEOHP(value));
276276
}
277277
else
278278
sz += datumGetSize(value, typByVal, typLen);
@@ -286,6 +286,13 @@ datumEstimateSpace(Datum value, bool isnull, bool typByVal, int typLen)
286286
*
287287
* Serialize a possibly-NULL datum into caller-provided storage.
288288
*
289+
* Note: "expanded" objects are flattened so as to produce a self-contained
290+
* representation, but other sorts of toast pointers are transferred as-is.
291+
* This is because the intended use of this function is to pass the value
292+
* to another process within the same database server. The other process
293+
* could not access an "expanded" object within this process's memory, but
294+
* we assume it can dereference the same TOAST pointers this one can.
295+
*
289296
* The format is as follows: first, we write a 4-byte header word, which
290297
* is either the length of a pass-by-reference datum, -1 for a
291298
* pass-by-value datum, or -2 for a NULL. If the value is NULL, nothing
@@ -310,7 +317,8 @@ datumSerialize(Datum value, bool isnull, bool typByVal, int typLen,
310317
header = -2;
311318
else if (typByVal)
312319
header = -1;
313-
else if (VARATT_IS_EXTERNAL_EXPANDED(value))
320+
else if (typLen == -1 &&
321+
VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(value)))
314322
{
315323
eoh = DatumGetEOHP(value);
316324
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