[PATCH] Avoid internal error for invalid interval typmods

From: Feng Wu <wufengwufengwufeng(at)gmail(dot)com>
To: pgsql-hackers(at)lists(dot)postgresql(dot)org
Subject: [PATCH] Avoid internal error for invalid interval typmods
Date: 2026-06-30 04:18:36
Message-ID: CACK3murBjJ6Ei_XJy-DQWS2eZmm6MEyhzEawNksF4G6CbdtA=A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

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.

Tested with the interval regression test.

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);

Browse pgsql-hackers by date

  From Date Subject
Next Message jian he 2026-06-30 04:20:57 Re: statatt_build_stavalues->LOCAL_FCINFO wrong number
Previous Message solai v 2026-06-30 04:08:29 Re: [SP-]GiST IOS visibility bug (was: Why doens't GiST require super-exclusive lock)