• Tom Lane's avatar
    Fix integer-overflow problems in interval comparison. · df1a699e
    Tom Lane authored
    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 146604ec 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
    df1a699e
interval.sql 11.9 KB