On Mon, Jun 29, 2026 at 9:26 PM Feng Wu <[email protected]> wrote:
>
> Hi,
>
> While fuzzing PostgreSQL, I noticed that the interval length-coercion
> function can report an internal error for user-supplied input:
>
>   SELECT pg_catalog.interval(interval '1 day', 1539);
>
> Currently this fails with:
>
>   ERROR:  unrecognized interval typmod: 1539
>
> The error is raised with elog(ERROR) in AdjustIntervalForTypmod(), so it
> is reported as SQLSTATE XX000.  Since pg_catalog.interval(interval, int4)
> is callable from SQL, arbitrary typmod values can reach this path.
>
> The patch below changes that case to report
> ERRCODE_INVALID_PARAMETER_VALUE instead, matching the nearby precision
> validation in the same function.  It also adds a regression test that
> catches the error as invalid_parameter_value.
>

I wonder whether AdjustIntervalForTypmod() should be changed too.
pg_catalog.interval(interval, int4) is SQL-callable, so users can pass
arbitrary typmod values directly. If such an invalid typmod reaches
AdjustIntervalForTypmod(), reporting XX000 seems inappropriate, since
it is not really an internal error but invalid user input.

> Tested with the interval regression test.
>

Could we use ERRCODE_INVALID_PARAMETER_VALUE for this case and add a
regression test covering a direct call to
pg_catalog.interval(interval, int4) with an invalid typmod?

> Regards,
> Feng
>
> ---
>  src/backend/utils/adt/timestamp.c      |  4 +++-
>  src/test/regress/expected/interval.out | 10 ++++++++++
>  src/test/regress/sql/interval.sql      |  9 +++++++++
>  3 files changed, 22 insertions(+), 1 deletion(-)
>
> diff --git a/src/backend/utils/adt/timestamp.c
> b/src/backend/utils/adt/timestamp.c
> index a20e7ea1..01b9ed52 100644
> --- a/src/backend/utils/adt/timestamp.c
> +++ b/src/backend/utils/adt/timestamp.c
> @@ -1489,7 +1489,9 @@ AdjustIntervalForTypmod(Interval *interval, int32 
> typmod,
>                         /* fractional-second rounding will be dealt with 
> below */
>                 }
>                 else
> -                       elog(ERROR, "unrecognized interval typmod: %d", 
> typmod);
> +                       ereturn(escontext, false,
> +                                       
> (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
> +                                        errmsg("unrecognized interval 
> typmod: %d", typmod)));
>
>                 /* Need to adjust sub-second precision? */
>                 if (precision != INTERVAL_FULL_PRECISION)
> diff --git a/src/test/regress/expected/interval.out
> b/src/test/regress/expected/interval.out
> index a16e3ccd..c5e10482 100644
> --- a/src/test/regress/expected/interval.out
> +++ b/src/test/regress/expected/interval.out
> @@ -857,6 +857,16 @@ SELECT interval(2) '1 day 01:23:45.6789';
>   1 day 01:23:45.68
>  (1 row)
>
> +-- invalid typmods passed to the length-coercion function are user errors,
> +-- not internal errors
> +DO $$
> +BEGIN
> +  PERFORM pg_catalog.interval(interval '1 day', 1539);
> +EXCEPTION WHEN invalid_parameter_value THEN
> +  RAISE NOTICE 'invalid interval typmod rejected';
> +END
> +$$;
> +NOTICE:  invalid interval typmod rejected
>  SELECT interval '12:34.5678' minute to second(2);  -- per SQL spec
>    interval
>  -------------
> diff --git a/src/test/regress/sql/interval.sql
> b/src/test/regress/sql/interval.sql
> index 43bc7939..88794c21 100644
> --- a/src/test/regress/sql/interval.sql
> +++ b/src/test/regress/sql/interval.sql
> @@ -257,6 +257,15 @@ SELECT interval '123 2:03 -2:04'; -- not ok,
> redundant hh:mm fields
>  -- test syntaxes for restricted precision
>  SELECT interval(0) '1 day 01:23:45.6789';
>  SELECT interval(2) '1 day 01:23:45.6789';
> +-- invalid typmods passed to the length-coercion function are user errors,
> +-- not internal errors
> +DO $$
> +BEGIN
> +  PERFORM pg_catalog.interval(interval '1 day', 1539);
> +EXCEPTION WHEN invalid_parameter_value THEN
> +  RAISE NOTICE 'invalid interval typmod rejected';
> +END
> +$$;
>  SELECT interval '12:34.5678' minute to second(2);  -- per SQL spec
>  SELECT interval '1.234' second;
>  SELECT interval '1.234' second(2);
> --
> 2.50.1 (Apple Git-155)
>
>

Regards
Haibo


Reply via email to