Author: yuripv
Date: Wed Oct 17 14:51:43 2018
New Revision: 339408
URL: https://svnweb.freebsd.org/changeset/base/339408

Log:
  strptime: fix parsing of tm_year when both %C and %y appear in the
  format string in arbitrary order.  This makes the related test cases in
  lib/libc/tests/time (not yet connected to the build) pass.
  
  While here, don't error on negative tm_year value based on the
  APPLICATION USAGE in
  http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/time.h.html
  (glibc does the same):
  
  tm_year is a signed value; therefore, years before 1900 may be represented.
  
  Approved by:  re (gjb), kib (mentor)
  Differential Revision:        https://reviews.freebsd.org/D17550

Modified:
  head/lib/libc/stdtime/strptime.c

Modified: head/lib/libc/stdtime/strptime.c
==============================================================================
--- head/lib/libc/stdtime/strptime.c    Wed Oct 17 10:31:08 2018        
(r339407)
+++ head/lib/libc/stdtime/strptime.c    Wed Oct 17 14:51:43 2018        
(r339408)
@@ -95,6 +95,7 @@ _strptime(const char *buf, const char *fmt, struct tm 
        int     i, len;
        int flags;
        int Ealternative, Oalternative;
+       int century, year;
        const struct lc_time_T *tptr = __get_current_time_locale(locale);
        static int start_of_month[2][13] = {
                {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
@@ -102,6 +103,8 @@ _strptime(const char *buf, const char *fmt, struct tm 
        };
 
        flags = FLAG_NONE;
+       century = -1;
+       year = -1;
 
        ptr = fmt;
        while (*ptr != 0) {
@@ -146,10 +149,8 @@ label:
                                i += *buf - '0';
                                len--;
                        }
-                       if (i < 19)
-                               return (NULL);
 
-                       tm->tm_year = i * 100 - TM_YEAR_BASE;
+                       century = i;
                        flags |= FLAG_YEAR;
 
                        break;
@@ -527,13 +528,9 @@ label:
                                len--;
                        }
                        if (c == 'Y')
-                               i -= TM_YEAR_BASE;
-                       if (c == 'y' && i < 69)
-                               i += 100;
-                       if (i < 0)
-                               return (NULL);
+                               century = i / 100;
+                       year = i % 100;
 
-                       tm->tm_year = i;
                        flags |= FLAG_YEAR;
 
                        break;
@@ -609,6 +606,17 @@ label:
                default:
                        return (NULL);
                }
+       }
+
+       if (century != -1 || year != -1) {
+               if (year == -1)
+                       year = 0;
+               if (century == -1) {
+                       if (year < 69)
+                               year += 100;
+               } else
+                       year += century * 100 - TM_YEAR_BASE;
+               tm->tm_year = year;
        }
 
        if (!(flags & FLAG_YDAY) && (flags & FLAG_YEAR)) {
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to