]> granicus.if.org Git - postgresql/commitdiff
Ensure that snprintf.c's fmtint() doesn't overflow when printing INT64_MIN.
authorAndres Freund <andres@anarazel.de>
Wed, 3 Oct 2018 20:02:25 +0000 (13:02 -0700)
committerAndres Freund <andres@anarazel.de>
Wed, 3 Oct 2018 20:13:50 +0000 (13:13 -0700)
This isn't actually a live bug, as the output happens to be the
same.  But it upsets tools like UBSan, which makes it worthwhile to
fix.

As it's an issue without practical consequences, don't backpatch.

Author: Andres Freund
Discussion: https://postgr.es/m/20180928001121.hhx5n6dsygqxr5wu@alap3.anarazel.de

src/port/snprintf.c

index 3bd598d75c66a8feb9f024c355b62756d57cd227..872d80012401a1fb13a475fdf80b82553da68812 100644 (file)
@@ -1007,6 +1007,7 @@ fmtint(long long value, char type, int forcesign, int leftjust,
           PrintfTarget *target)
 {
        unsigned long long base;
+       unsigned long long uvalue;
        int                     dosign;
        const char *cvt = "0123456789abcdef";
        int                     signvalue = 0;
@@ -1045,7 +1046,9 @@ fmtint(long long value, char type, int forcesign, int leftjust,
 
        /* Handle +/- */
        if (dosign && adjust_sign((value < 0), forcesign, &signvalue))
-               value = -value;
+               uvalue = -(uint64) value;
+       else
+               uvalue = (uint64) value;
 
        /*
         * SUS: the result of converting 0 with an explicit precision of 0 is no
@@ -1056,8 +1059,6 @@ fmtint(long long value, char type, int forcesign, int leftjust,
        else
        {
                /* make integer string */
-               unsigned long long uvalue = (unsigned long long) value;
-
                do
                {
                        convert[sizeof(convert) - (++vallen)] = cvt[uvalue % base];