Thread: Fix overflow in justify_interval related functions

Fix overflow in justify_interval related functions

From
Joseph Koshakow
Date:
I mentioned this issue briefly in another thread, but the
justify_interval, justify_days, and justify_hours functions
all have the potential to overflow. The attached patch fixes
this issue.

Cheers,
Joe Koshakow

Attachment

Re: Fix overflow in justify_interval related functions

From
Nathan Bossart
Date:
On Sun, Feb 13, 2022 at 01:28:38PM -0500, Joseph Koshakow wrote:
> +SELECT justify_hours(interval '2147483647 days 24 hrs');
> +ERROR:  interval out of range

The docs [0] claim that the maximum value for interval is 178 million
years, but this test case is only ~6 million.  Should we instead rework the
logic to avoid overflow for this case?

[0] https://www.postgresql.org/docs/devel/datatype-datetime.html

-- 
Nathan Bossart
Amazon Web Services: https://aws.amazon.com



Re: Fix overflow in justify_interval related functions

From
Tom Lane
Date:
Nathan Bossart <nathandbossart@gmail.com> writes:
> On Sun, Feb 13, 2022 at 01:28:38PM -0500, Joseph Koshakow wrote:
>> +SELECT justify_hours(interval '2147483647 days 24 hrs');
>> +ERROR:  interval out of range

> The docs [0] claim that the maximum value for interval is 178 million
> years, but this test case is only ~6 million.  Should we instead rework the
> logic to avoid overflow for this case?

I think the docs are misleading you on this point.  The maximum
value of the months part of an interval is 2^31 months or
about 178Myr, but what we're dealing with here is days, which
likewise caps at 2^31 days.  justify_hours is not chartered
to transpose up to months, so it can't avoid that limit.

            regards, tom lane



Re: Fix overflow in justify_interval related functions

From
Nathan Bossart
Date:
On Mon, Feb 14, 2022 at 01:55:56PM -0500, Tom Lane wrote:
> Nathan Bossart <nathandbossart@gmail.com> writes:
>> On Sun, Feb 13, 2022 at 01:28:38PM -0500, Joseph Koshakow wrote:
>>> +SELECT justify_hours(interval '2147483647 days 24 hrs');
>>> +ERROR:  interval out of range
> 
>> The docs [0] claim that the maximum value for interval is 178 million
>> years, but this test case is only ~6 million.  Should we instead rework the
>> logic to avoid overflow for this case?
> 
> I think the docs are misleading you on this point.  The maximum
> value of the months part of an interval is 2^31 months or
> about 178Myr, but what we're dealing with here is days, which
> likewise caps at 2^31 days.  justify_hours is not chartered
> to transpose up to months, so it can't avoid that limit.

Makes sense.  So we could likely avoid it for justify_interval, but the
others are at the mercy of the interval implementation.

-- 
Nathan Bossart
Amazon Web Services: https://aws.amazon.com



Re: Fix overflow in justify_interval related functions

From
Joseph Koshakow
Date:
On Mon, Feb 14, 2022 at 2:15 PM Nathan Bossart <nathandbossart@gmail.com> wrote:
> Makes sense.  So we could likely avoid it for justify_interval, but the
> others are at the mercy of the interval implementation.

I'm not entirely sure what you mean by "it", but for both
justify_interval and justify_days this commit throws an error if we
try to set the months field above 2^31.

> +SELECT justify_days(interval '2147483647 months 30 days');
> +ERROR:  interval out of range
> +SELECT justify_interval(interval '2147483647 months 30 days');
> +ERROR:  interval out of range

That's what these are testing.

- Joe Koshakow



Re: Fix overflow in justify_interval related functions

From
Nathan Bossart
Date:
On Mon, Feb 14, 2022 at 04:57:07PM -0500, Joseph Koshakow wrote:
> On Mon, Feb 14, 2022 at 2:15 PM Nathan Bossart <nathandbossart@gmail.com> wrote:
>> Makes sense.  So we could likely avoid it for justify_interval, but the
>> others are at the mercy of the interval implementation.
> 
> I'm not entirely sure what you mean by "it", but for both
> justify_interval and justify_days this commit throws an error if we
> try to set the months field above 2^31.
> 
>> +SELECT justify_days(interval '2147483647 months 30 days');
>> +ERROR:  interval out of range
>> +SELECT justify_interval(interval '2147483647 months 30 days');
>> +ERROR:  interval out of range
> 
> That's what these are testing.

I think it's possible to avoid overflow in justify_interval() in some cases
by pre-justifying the days.  I've attached a patch to demonstrate.

-- 
Nathan Bossart
Amazon Web Services: https://aws.amazon.com

Attachment

Re: Fix overflow in justify_interval related functions

From
Joseph Koshakow
Date:
On Mon, Feb 14, 2022 at 7:59 PM Nathan Bossart <nathandbossart@gmail.com> wrote:
> I think it's possible to avoid overflow in justify_interval() in some cases
> by pre-justifying the days.  I've attached a patch to demonstrate.
>
> --
> Nathan Bossart
> Amazon Web Services: https://aws.amazon.com

Good catch, I didn't think about that. Though if you are pre-justifying
the days, then I don't think it's possible for the second addition to
days to overflow. The maximum amount the days field could be after
the first justification is 29. I think we can simplify it further to the
attached patch.

- Joe

Attachment

Re: Fix overflow in justify_interval related functions

From
Nathan Bossart
Date:
On Mon, Feb 14, 2022 at 08:35:43PM -0500, Joseph Koshakow wrote:
> Good catch, I didn't think about that. Though if you are pre-justifying
> the days, then I don't think it's possible for the second addition to
> days to overflow. The maximum amount the days field could be after
> the first justification is 29. I think we can simplify it further to the
> attached patch.

LGTM.  I've marked this one as ready-for-committer.  It's a little weird
that justify_hours() and justify_days() can overflow in cases where there
is still a valid interval representation, but as Tom noted, those functions
have specific charters to follow.

> +        ereport(ERROR,
> +                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
> +                errmsg("interval out of range")));

nitpick: I think there is ordinarily an extra space before errmsg() so that
it lines up with errcode().

-- 
Nathan Bossart
Amazon Web Services: https://aws.amazon.com



Re: Fix overflow in justify_interval related functions

From
Joseph Koshakow
Date:
On Mon, Feb 14, 2022 at 11:23 PM Nathan Bossart
<nathandbossart@gmail.com> wrote:
> It's a little weird
> that justify_hours() and justify_days() can overflow in cases where there
> is still a valid interval representation, but as Tom noted, those functions
> have specific charters to follow.

Yes it is a bit weird, but this follows the same behavior as adding
Intervals. The following query overflows:
  postgres=# SELECT interval '2147483647 days' + interval '1 day';
  ERROR:  interval out of range
Even though the following query does not:
  postgres=# SELECT justify_days(interval '2147483647 days') + interval '1 day';
            ?column?
  -----------------------------
   5965232 years 4 mons 8 days
  (1 row)

The reason is, as Tom mentioned, that Interval's months, days, and
time (microseconds) are stored separately. They are only combined
during certain scenarios such as testing for equality, ordering,
justify_* methods, etc. I think the idea behind it is that not every month
has 30 days and not every day has 24 hrs, though I'm not sure
.
> > +             ereport(ERROR,
> > +                             (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
> > +                             errmsg("interval out of range")));
>
> nitpick: I think there is ordinarily an extra space before errmsg() so that
> it lines up with errcode().

I've attached a patch to add the space. Thanks so much for your review
and comments!

- Joe Koshakow

Attachment

Re: Fix overflow in justify_interval related functions

From
Joseph Koshakow
Date:
Just checking because I'm not very familiar with the process,
are there any outstanding items that I need to do for this patch?

- Joe Koshakow



Re: Fix overflow in justify_interval related functions

From
Nathan Bossart
Date:
On Fri, Feb 25, 2022 at 10:30:57AM -0500, Joseph Koshakow wrote:
> Just checking because I'm not very familiar with the process,
> are there any outstanding items that I need to do for this patch?

Unless someone has additional feedback, I don't think so.

-- 
Nathan Bossart
Amazon Web Services: https://aws.amazon.com



Re: Fix overflow in justify_interval related functions

From
Tom Lane
Date:
Joseph Koshakow <koshy44@gmail.com> writes:
> [ v4-0001-Check-for-overflow-in-justify_interval-functions.patch ]

Pushed.  I added a comment explaining why the one addition in
interval_justify_interval doesn't require an overflow check.

            regards, tom lane