diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2020-07-21 15:19:46 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2020-07-21 15:19:46 -0400 |
commit | 670c0a1d474bf296dbcc1d6de912d4841f2ed643 (patch) | |
tree | e4a97a14031448cbf3be40914b6708db161a329c /src/backend/utils/adt/arrayfuncs.c | |
parent | 606c3845988ddd9497cbbbf6fc559b91c76ed65d (diff) | |
download | postgresql-670c0a1d474bf296dbcc1d6de912d4841f2ed643.tar.gz postgresql-670c0a1d474bf296dbcc1d6de912d4841f2ed643.zip |
Weaken type-OID-matching checks in array_recv and record_recv.
Rather than always insisting on an exact match of the type OID in the
data to the element type or column type we expect, complain only when
both OIDs fall within the manually-assigned range. This acknowledges
the reality that user-defined types don't have stable OIDs, while
still preserving some of the mistake-detection value of the old test.
(It's not entirely clear whether to error if one OID is manually
assigned and the other isn't. But perhaps that case could arise in
cross-version cases where a former extension type has been imported
into core, so I let it pass.)
This change allows us to remove the prohibition on binary transfer
of user-defined arrays and composites in the recently-landed support
for binary logical replication (commit 9de77b545). We can just
unconditionally drop that check, since if the client has asked for
binary transfer it must be >= v14 and must have this change.
Discussion: https://postgr.es/m/CADK3HH+R3xMn=8t3Ct+uD+qJ1KD=Hbif5NFMJ+d5DkoCzp6Vgw@mail.gmail.com
Diffstat (limited to 'src/backend/utils/adt/arrayfuncs.c')
-rw-r--r-- | src/backend/utils/adt/arrayfuncs.c | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index 800107d4e72..392445ea032 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -1308,13 +1308,34 @@ array_recv(PG_FUNCTION_ARGS) (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid array flags"))); + /* Check element type recorded in the data */ element_type = pq_getmsgint(buf, sizeof(Oid)); + + /* + * From a security standpoint, it doesn't matter whether the input's + * element type matches what we expect: the element type's receive + * function has to be robust enough to cope with invalid data. However, + * from a user-friendliness standpoint, it's nicer to complain about type + * mismatches than to throw "improper binary format" errors. But there's + * a problem: only built-in types have OIDs that are stable enough to + * believe that a mismatch is a real issue. So complain only if both OIDs + * are in the built-in range. Otherwise, carry on with the element type + * we "should" be getting. + */ if (element_type != spec_element_type) { - /* XXX Can we allow taking the input element type in any cases? */ - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("wrong element type"))); + if (element_type < FirstGenbkiObjectId && + spec_element_type < FirstGenbkiObjectId) + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("binary data has array element type %u (%s) instead of expected %u (%s)", + element_type, + format_type_extended(element_type, -1, + FORMAT_TYPE_ALLOW_INVALID), + spec_element_type, + format_type_extended(spec_element_type, -1, + FORMAT_TYPE_ALLOW_INVALID)))); + element_type = spec_element_type; } for (i = 0; i < ndim; i++) |