Fix division by zero error in date_bin
authorJohn Naylor <john.naylor@postgresql.org>
Thu, 22 Jul 2021 21:34:19 +0000 (17:34 -0400)
committerJohn Naylor <john.naylor@postgresql.org>
Thu, 22 Jul 2021 21:34:19 +0000 (17:34 -0400)
Bauyrzhan Sakhariyev, via Github

Backpatch to v14

src/backend/utils/adt/timestamp.c
src/test/regress/expected/timestamp.out
src/test/regress/expected/timestamptz.out
src/test/regress/sql/timestamp.sql
src/test/regress/sql/timestamptz.sql

index 79761f809c8ed32eeb6fffe6cf1d149adda8d43b..ea847576cd2aa532dfcdbc961f32a490bcf75964 100644 (file)
@@ -3843,6 +3843,11 @@ timestamp_bin(PG_FUNCTION_ARGS)
 
    stride_usecs = stride->day * USECS_PER_DAY + stride->time;
 
+   if (stride_usecs == 0)
+       ereport(ERROR,
+               (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+                errmsg("stride cannot equal zero")));
+
    tm_diff = timestamp - origin;
    tm_delta = tm_diff - tm_diff % stride_usecs;
 
@@ -4021,6 +4026,11 @@ timestamptz_bin(PG_FUNCTION_ARGS)
 
    stride_usecs = stride->day * USECS_PER_DAY + stride->time;
 
+   if (stride_usecs == 0)
+       ereport(ERROR,
+               (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+                errmsg("stride cannot equal zero")));
+
    tm_diff = timestamp - origin;
    tm_delta = tm_diff - tm_diff % stride_usecs;
 
index 6fdca6b295cbab77ba1f91880d922397727ba4bb..7a2cbd9b3f0d0dc6643c9fe51d6945b9d8c3bc86 100644 (file)
@@ -704,6 +704,9 @@ SELECT date_bin('5 months'::interval, timestamp '2020-02-01 01:01:01', timestamp
 ERROR:  timestamps cannot be binned into intervals containing months or years
 SELECT date_bin('5 years'::interval,  timestamp '2020-02-01 01:01:01', timestamp '2001-01-01');
 ERROR:  timestamps cannot be binned into intervals containing months or years
+-- disallow zero intervals
+SELECT date_bin('0 days'::interval, timestamp '1970-01-01 01:00:00' , timestamp '1970-01-01 00:00:00');
+ERROR:  stride cannot equal zero
 -- Test casting within a BETWEEN qualifier
 SELECT d1 - timestamp without time zone '1997-01-02' AS diff
   FROM TIMESTAMP_TBL
index 421ef2578ac52bc759b9a7c81898f4d785b5ec2e..be6ead0fb509f4c30361ff2a8617652979f2a738 100644 (file)
@@ -748,6 +748,9 @@ SELECT date_bin('5 months'::interval, timestamp with time zone '2020-02-01 01:01
 ERROR:  timestamps cannot be binned into intervals containing months or years
 SELECT date_bin('5 years'::interval,  timestamp with time zone '2020-02-01 01:01:01+00', timestamp with time zone '2001-01-01+00');
 ERROR:  timestamps cannot be binned into intervals containing months or years
+-- disallow zero intervals
+SELECT date_bin('0 days'::interval, timestamp with time zone '1970-01-01 01:00:00+00' , timestamp with time zone '1970-01-01 00:00:00+00');
+ERROR:  stride cannot equal zero
 -- Test casting within a BETWEEN qualifier
 SELECT d1 - timestamp with time zone '1997-01-02' AS diff
   FROM TIMESTAMPTZ_TBL
index 2841d2f2af462c76808f870ddd75eb1918260659..7307a2409271b7420248e7029bbb41a828b1d09b 100644 (file)
@@ -263,6 +263,9 @@ SELECT date_bin('5 min'::interval, timestamp '2020-02-01 01:01:01', timestamp '2
 SELECT date_bin('5 months'::interval, timestamp '2020-02-01 01:01:01', timestamp '2001-01-01');
 SELECT date_bin('5 years'::interval,  timestamp '2020-02-01 01:01:01', timestamp '2001-01-01');
 
+-- disallow zero intervals
+SELECT date_bin('0 days'::interval, timestamp '1970-01-01 01:00:00' , timestamp '1970-01-01 00:00:00');
+
 -- Test casting within a BETWEEN qualifier
 SELECT d1 - timestamp without time zone '1997-01-02' AS diff
   FROM TIMESTAMP_TBL
index 17ced99efca32e20137ec8c64d93d33678ecea95..3642d8c143cad3faaa4f37b437a05265bf3dc6a1 100644 (file)
@@ -238,6 +238,9 @@ SELECT date_bin('5 min'::interval, timestamptz '2020-02-01 01:01:01+00', timesta
 SELECT date_bin('5 months'::interval, timestamp with time zone '2020-02-01 01:01:01+00', timestamp with time zone '2001-01-01+00');
 SELECT date_bin('5 years'::interval,  timestamp with time zone '2020-02-01 01:01:01+00', timestamp with time zone '2001-01-01+00');
 
+-- disallow zero intervals
+SELECT date_bin('0 days'::interval, timestamp with time zone '1970-01-01 01:00:00+00' , timestamp with time zone '1970-01-01 00:00:00+00');
+
 -- Test casting within a BETWEEN qualifier
 SELECT d1 - timestamp with time zone '1997-01-02' AS diff
   FROM TIMESTAMPTZ_TBL