PL/pgSQL: fix validation of anycompatiblemultirange

Started by Jeevan Chalkeabout 12 hours ago3 messageshackers
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

won't retrysuccessCI history

This thread has been committed, so CI has stopped here. Anything below is the last result it produced.

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t254392
psql -h localhost -U postgres

Built from patchset v1 (message #1), October 26, 2026 at 01:20 PM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t254392_1 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t254392_1 && git checkout t254392_1

Patchset v1 (message #1) is on t254392_1

Jump to latest
#1Jeevan Chalke
jeevan.chalke@enterprisedb.com

Hi,

When validating a PL/pgSQL function with polymorphic arguments or result
type,
we substitute a plausible concrete type for each polymorphic type. This is
done in two places, cfunc_resolve_polymorphic_argtypes() in funccache.c for
arguments and plpgsql_compile_callback() in pl_comp.c for the result type.
Both handle anycompatiblerange and anymultirange, but neither handles
anycompatiblemultirange. This appears to have been missed when multiranges
were added in 6df7a9698bb (v14), which added the anymultirange case to both
places but did not add any PL/pgSQL test for anycompatiblemultirange.

This has two visible effects. First, with check_function_bodies = ON,
creating
a function with an anycompatiblemultirange argument fails:

CREATE FUNCTION f1(x anycompatiblemultirange)
RETURNS anycompatiblemultirange AS $$
BEGIN RETURN x; END $$ LANGUAGE plpgsql;
ERROR: PL/pgSQL functions cannot accept type anycompatiblemultirange

The same function can be created with check_function_bodies = off, and then
works, so only the validation path is wrong.

Second, a function that only returns anycompatiblemultirange is compiled by
the validator with an int4 result type. The function cache key does not
include the result type, so a later call in the same session with the same
argument types the validator used (int4range here) reuses that entry, and
fails:

CREATE FUNCTION f1(x anycompatiblerange)
RETURNS anycompatiblemultirange AS $$
BEGIN RETURN multirange(x); END $$ LANGUAGE plpgsql;
SELECT f1(int4range(42, 49));
ERROR: invalid input syntax for type integer: "{[42,49)}"

A call with other argument types, say numrange, gets its own cache entry and
works, which is why this can go unnoticed.

The attached patch maps anycompatiblemultirange to int4multirange in both
places, as is already done for anymultirange, which fixes both issues.

It also adds two regression tests to plpgsql.sql, one for each case above.
Both fail without the fix.

Since this is a plain bug fix, I think it should be back-patched to v14,
where
anycompatiblemultirange was introduced, but I'd like to hear what others
think. On branches before v18 the argument-type fix would go in pl_comp.c,
since cfunc_resolve_polymorphic_argtypes() in funccache.c is newer.

Thanks

--
*Jeevan Chalke*
*Senior Principal Engineer, Engineering Manager*
*Product Development*

enterprisedb.com <https://www.enterprisedb.com&gt;

Attachments:

t254392_1
v1-0001-Fix-PL-pgSQL-validation-of-anycompatiblemultirang.patchapplication/octet-stream; name=v1-0001-Fix-PL-pgSQL-validation-of-anycompatiblemultirang.patchDownload+47-2
#2Pavel Stehule
pavel.stehule@gmail.com
In reply to: Jeevan Chalke (#1)
Re: PL/pgSQL: fix validation of anycompatiblemultirange

Hi

po 26. 10. 2026 v 14:06 odesílatel Jeevan Chalke <
jeevan.chalke@enterprisedb.com> napsal:

Hi,

When validating a PL/pgSQL function with polymorphic arguments or result
type,
we substitute a plausible concrete type for each polymorphic type. This is
done in two places, cfunc_resolve_polymorphic_argtypes() in funccache.c
for
arguments and plpgsql_compile_callback() in pl_comp.c for the result type.
Both handle anycompatiblerange and anymultirange, but neither handles
anycompatiblemultirange. This appears to have been missed when
multiranges
were added in 6df7a9698bb (v14), which added the anymultirange case to
both
places but did not add any PL/pgSQL test for anycompatiblemultirange.

This has two visible effects. First, with check_function_bodies = ON,
creating
a function with an anycompatiblemultirange argument fails:

CREATE FUNCTION f1(x anycompatiblemultirange)
RETURNS anycompatiblemultirange AS $$
BEGIN RETURN x; END $$ LANGUAGE plpgsql;
ERROR: PL/pgSQL functions cannot accept type anycompatiblemultirange

The same function can be created with check_function_bodies = off, and
then
works, so only the validation path is wrong.

Second, a function that only returns anycompatiblemultirange is compiled
by
the validator with an int4 result type. The function cache key does not
include the result type, so a later call in the same session with the same
argument types the validator used (int4range here) reuses that entry, and
fails:

CREATE FUNCTION f1(x anycompatiblerange)
RETURNS anycompatiblemultirange AS $$
BEGIN RETURN multirange(x); END $$ LANGUAGE plpgsql;
SELECT f1(int4range(42, 49));
ERROR: invalid input syntax for type integer: "{[42,49)}"

A call with other argument types, say numrange, gets its own cache entry
and
works, which is why this can go unnoticed.

The attached patch maps anycompatiblemultirange to int4multirange in both
places, as is already done for anymultirange, which fixes both issues.

It also adds two regression tests to plpgsql.sql, one for each case above.
Both fail without the fix.

Since this is a plain bug fix, I think it should be back-patched to v14,
where
anycompatiblemultirange was introduced, but I'd like to hear what others
think. On branches before v18 the argument-type fix would go in pl_comp.c
,
since cfunc_resolve_polymorphic_argtypes() in funccache.c is newer.

+1

Pavel

Show quoted text

Thanks

--
*Jeevan Chalke*
*Senior Principal Engineer, Engineering Manager*
*Product Development*

enterprisedb.com <https://www.enterprisedb.com&gt;

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Jeevan Chalke (#1)
Re: PL/pgSQL: fix validation of anycompatiblemultirange

Jeevan Chalke <jeevan.chalke@enterprisedb.com> writes:

When validating a PL/pgSQL function with polymorphic arguments or result
type,
we substitute a plausible concrete type for each polymorphic type. This is
done in two places, cfunc_resolve_polymorphic_argtypes() in funccache.c for
arguments and plpgsql_compile_callback() in pl_comp.c for the result type.
Both handle anycompatiblerange and anymultirange, but neither handles
anycompatiblemultirange. This appears to have been missed when multiranges
were added in 6df7a9698bb (v14), which added the anymultirange case to both
places but did not add any PL/pgSQL test for anycompatiblemultirange.

Good catch, fix pushed. I didn't bother with the test cases though,
as they seem too specific to help us catch any future problems.

regards, tom lane