Check integer conversion for overflow in datetime functions.  Problem
reported by Christopher Kings-Lynne:

http://archives.postgresql.org/pgsql-hackers/2005-11/msg01385.php

In one place (line 60 in the patch) the code sets errno to 0 when
it should still be 0 after similar code a few lines above (otherwise
the function would have returned an error).  I wasn't sure what
would be preferred: clearing errno again "just to be sure," a comment
explaining why it isn't necessary, or nothing at all.

This patch should apply cleanly against HEAD and 8.1.  If the patch
looks good then I'll submit patches for earlier branches when I get
a chance to build and test those versions.

-- 
Michael Fuhr
Index: src/backend/utils/adt/datetime.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/datetime.c,v
retrieving revision 1.160.2.1
diff -c -r1.160.2.1 datetime.c
*** src/backend/utils/adt/datetime.c    22 Nov 2005 18:23:21 -0000      
1.160.2.1
--- src/backend/utils/adt/datetime.c    1 Dec 2005 01:12:01 -0000
***************
*** 1013,1019 ****
--- 1013,1022 ----
                                        if (tzp == NULL)
                                                return DTERR_BAD_FORMAT;
  
+                                       errno = 0;
                                        val = strtol(field[i], &cp, 10);
+                                       if (errno == ERANGE)
+                                               return DTERR_FIELD_OVERFLOW;
  
                                        j2date(val, &tm->tm_year, &tm->tm_mon, 
&tm->tm_mday);
                                        /* Get the time zone from the end of 
the string */
***************
*** 1158,1164 ****
--- 1161,1170 ----
                                        char       *cp;
                                        int                     val;
  
+                                       errno = 0;
                                        val = strtol(field[i], &cp, 10);
+                                       if (errno == ERANGE)
+                                               return DTERR_FIELD_OVERFLOW;
  
                                        /*
                                         * only a few kinds are allowed to have 
an embedded
***************
*** 1915,1921 ****
--- 1921,1930 ----
                                                        break;
                                        }
  
+                                       errno = 0;
                                        val = strtol(field[i], &cp, 10);
+                                       if (errno == ERANGE)
+                                               return DTERR_FIELD_OVERFLOW;
  
                                        /*
                                         * only a few kinds are allowed to have 
an embedded
***************
*** 2456,2466 ****
--- 2465,2481 ----
  
        *tmask = DTK_TIME_M;
  
+       errno = 0;
        tm->tm_hour = strtol(str, &cp, 10);
+       if (errno == ERANGE)
+               return DTERR_FIELD_OVERFLOW;
        if (*cp != ':')
                return DTERR_BAD_FORMAT;
        str = cp + 1;
+       errno = 0;
        tm->tm_min = strtol(str, &cp, 10);
+       if (errno == ERANGE)
+               return DTERR_FIELD_OVERFLOW;
        if (*cp == '\0')
        {
                tm->tm_sec = 0;
***************
*** 2471,2477 ****
--- 2486,2495 ----
        else
        {
                str = cp + 1;
+               errno = 0;
                tm->tm_sec = strtol(str, &cp, 10);
+               if (errno == ERANGE)
+                       return DTERR_FIELD_OVERFLOW;
                if (*cp == '\0')
                        *fsec = 0;
                else if (*cp == '.')
***************
*** 2522,2528 ****
--- 2540,2549 ----
  
        *tmask = 0;
  
+       errno = 0;
        val = strtol(str, &cp, 10);
+       if (errno == ERANGE)
+               return DTERR_FIELD_OVERFLOW;
        if (cp == str)
                return DTERR_BAD_FORMAT;
  
***************
*** 2809,2819 ****
--- 2830,2848 ----
        if (*str != '+' && *str != '-')
                return DTERR_BAD_FORMAT;
  
+       errno = 0;
        hr = strtol(str + 1, &cp, 10);
+       if (errno == ERANGE)
+               return DTERR_TZDISP_OVERFLOW;
  
        /* explicit delimiter? */
        if (*cp == ':')
+       {
+               errno = 0;
                min = strtol(cp + 1, &cp, 10);
+               if (errno == ERANGE)
+                       return DTERR_TZDISP_OVERFLOW;
+       }
        /* otherwise, might have run things together... */
        else if (*cp == '\0' && strlen(str) > 3)
        {
***************
*** 3056,3062 ****
--- 3085,3094 ----
  
                        case DTK_DATE:
                        case DTK_NUMBER:
+                               errno = 0;
                                val = strtol(field[i], &cp, 10);
+                               if (errno == ERANGE)
+                                       return DTERR_FIELD_OVERFLOW;
  
                                if (type == IGNORE_DTF)
                                        type = DTK_SECOND;
---------------------------(end of broadcast)---------------------------
TIP 2: Don't 'kill -9' the postmaster

Reply via email to