pgsql: Fix integer-overflow problems in interval comparison.

Поиск
Список
Период
Сортировка
От Tom Lane
Тема pgsql: Fix integer-overflow problems in interval comparison.
Дата
Msg-id E1cvySh-0006ph-UF@gemulon.postgresql.org
обсуждение исходный текст
Список pgsql-committers
Fix integer-overflow problems in interval comparison.

When using integer timestamps, the interval-comparison functions tried
to compute the overall magnitude of an interval as an int64 number of
microseconds.  As reported by Frazer McLean, this overflows for intervals
exceeding about 296000 years, which is bad since we nominally allow
intervals many times larger than that.  That results in wrong comparison
results, and possibly in corrupted btree indexes for columns containing
such large interval values.

To fix, compute the magnitude as int128 instead.  Although some compilers
have native support for int128 calculations, many don't, so create our
own support functions that can do 128-bit addition and multiplication
if the compiler support isn't there.  These support functions are designed
with an eye to allowing the int128 code paths in numeric.c to be rewritten
for use on all platforms, although this patch doesn't do that, or even
provide all the int128 primitives that will be needed for it.

Back-patch as far as 9.4.  Earlier releases did not guard against overflow
of interval values at all (commit 146604ec4 fixed that), so it seems not
very exciting to worry about overly-large intervals for them.

Before 9.6, we did not assume that unreferenced "static inline" functions
would not draw compiler warnings, so omit functions not directly referenced
by timestamp.c, the only present consumer of int128.h.  (We could have
omitted these functions in HEAD too, but since they were written and
debugged on the way to the present patch, and they look likely to be needed
by numeric.c, let's keep them in HEAD.)  I did not bother to try to prevent
such warnings in a --disable-integer-datetimes build, though.

Before 9.5, configure will never define HAVE_INT128, so the part of
int128.h that exploits a native int128 implementation is dead code in the
9.4 branch.  I didn't bother to remove it, thinking that keeping the file
looking similar in different branches is more useful.

In HEAD only, add a simple test harness for int128.h in src/tools/.

In back branches, this does not change the float-timestamps code path.
That's not subject to the same kind of overflow risk, since it computes
the interval magnitude as float8.  (No doubt, when this code was originally
written, overflow was disregarded for exactly that reason.)  There is a
precision hazard instead :-(, but we'll avert our eyes from that question,
since no complaints have been reported and that code's deprecated anyway.

Kyotaro Horiguchi and Tom Lane

Discussion: https://postgr.es/m/1490104629.422698.918452336.26FA96B7@webmail.messagingengine.com

Branch
------
REL9_6_STABLE

Details
-------
http://git.postgresql.org/pg/commitdiff/fd52b88343308fabb13d6355db3c2565cdf91302

Modified Files
--------------
src/backend/utils/adt/timestamp.c      |  65 ++++++--
src/include/common/int128.h            | 276 +++++++++++++++++++++++++++++++++
src/test/regress/expected/interval.out |  64 ++++++++
src/test/regress/sql/interval.sql      |  27 ++++
4 files changed, 421 insertions(+), 11 deletions(-)


В списке pgsql-committers по дате отправления:

Предыдущее
От: Simon Riggs
Дата:
Сообщение: pgsql: Reduce lock level for CREATE STATISTICS
Следующее
От: Andres Freund
Дата:
Сообщение: pgsql: Code review for recent slot.c changes.