diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2018-12-20 15:58:58 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2018-12-20 16:21:59 -0500 |
commit | 5bbee34d9f2e6097247ace3ebe1dde1f6aa80287 (patch) | |
tree | 8d59b45b36a5dd01e7135263e0bb161e753fe49e /src/backend/utils | |
parent | 7b14bcc06cc56b110118fba408f4b9b72a663387 (diff) | |
download | postgresql-5bbee34d9f2e6097247ace3ebe1dde1f6aa80287.tar.gz postgresql-5bbee34d9f2e6097247ace3ebe1dde1f6aa80287.zip |
Avoid producing over-length specific_name outputs in information_schema.
information_schema output columns that are declared as being type
sql_identifier are supposed to conform to the implementation's rules
for valid identifiers, in particular the identifier length limit.
Several places potentially violated this limit by concatenating a
function's name and OID. (The OID is added to ensure name uniqueness
within a schema, since the spec doesn't expect function name overloading.)
Simply truncating the concatenation result to fit in "name" won't do,
since losing part of the OID might wind up giving non-unique results.
Instead, let's truncate the function name as necessary.
The most practical way to do that is to do it in a C function; the
information_schema.sql script doesn't have easy access to the value
of NAMEDATALEN, nor does it have an easy way to truncate on the basis
of resulting byte-length rather than number of characters.
(There are still a couple of places that cast concatenation results to
sql_identifier, but as far as I can see they are guaranteed not to produce
over-length strings, at least with the normal value of NAMEDATALEN.)
Discussion: https://postgr.es/m/23817.1545283477@sss.pgh.pa.us
Diffstat (limited to 'src/backend/utils')
-rw-r--r-- | src/backend/utils/adt/name.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/src/backend/utils/adt/name.c b/src/backend/utils/adt/name.c index 0cf8b9d46b5..eb35188e06f 100644 --- a/src/backend/utils/adt/name.c +++ b/src/backend/utils/adt/name.c @@ -364,3 +364,38 @@ current_schemas(PG_FUNCTION_ARGS) PG_RETURN_POINTER(array); } + +/* + * SQL-function nameconcatoid(name, oid) returns name + * + * This is used in the information_schema to produce specific_name columns, + * which are supposed to be unique per schema. We achieve that (in an ugly + * way) by appending the object's OID. The result is the same as + * ($1::text || '_' || $2::text)::name + * except that, if it would not fit in NAMEDATALEN, we make it do so by + * truncating the name input (not the oid). + */ +Datum +nameconcatoid(PG_FUNCTION_ARGS) +{ + Name nam = PG_GETARG_NAME(0); + Oid oid = PG_GETARG_OID(1); + Name result; + char suffix[20]; + int suflen; + int namlen; + + suflen = snprintf(suffix, sizeof(suffix), "_%u", oid); + namlen = strlen(NameStr(*nam)); + + /* Truncate oversize input by truncating name part, not suffix */ + if (namlen + suflen >= NAMEDATALEN) + namlen = pg_mbcliplen(NameStr(*nam), namlen, NAMEDATALEN - 1 - suflen); + + /* We use palloc0 here to ensure result is zero-padded */ + result = (Name) palloc0(NAMEDATALEN); + memcpy(NameStr(*result), NameStr(*nam), namlen); + memcpy(NameStr(*result) + namlen, suffix, suflen); + + PG_RETURN_NAME(result); +} |