[PATCH] Avoid internal error for invalid interval typmods - Mailing list pgsql-hackers

From Feng Wu
Subject [PATCH] Avoid internal error for invalid interval typmods
Date
Msg-id CACK3mup4yq52WuUYNY5SOS19ksNoeNTJmWa0c+zVXnm=hHeHJQ@mail.gmail.com
Whole thread
Responses Re: [PATCH] Avoid internal error for invalid interval typmods
List 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);
-- 
2.50.1 (Apple Git-155)



pgsql-hackers by date:

Previous
From: jian he
Date:
Subject: Re: statatt_build_stavalues->LOCAL_FCINFO wrong number
Next
From: Feng Wu
Date:
Subject: Re: [PATCH] Avoid internal error for invalid interval typmods