svn commit: r306416 - stable/9/lib/libc/stdtime

Andrey A. Chernov ache at FreeBSD.org
Wed Sep 28 20:54:48 UTC 2016


Author: ache
Date: Wed Sep 28 20:54:47 2016
New Revision: 306416
URL: https://svnweb.freebsd.org/changeset/base/306416

Log:
  MFC r306075,r306109
  
  1) Microoptimize %p case.
  2) Implememt %u for GNU compatibility.
  3) Don't forget to advance buf for %w/%u.
  4) Fail with incomplete week (week 0) request and no such week in the
  year.
  5) Fix yday formula when Sunday requested and the week started from Monday.
  6) Fail with impossible yday for incomplete week (week 0) and direct %w/%u
  request.
  7) Shift yday/wday to the first day of the year, if incomplete week
  (week 0) requested and no %w/%u used.
  8) For already non-standard %z extension implement GNU compatible formats:
  +hh and -hh.
  9) Check for incorrect values for %z.
  
  PR:     212983 (case 3 only)

Modified:
  stable/9/lib/libc/stdtime/strptime.c
Directory Properties:
  stable/9/   (props changed)
  stable/9/lib/   (props changed)
  stable/9/lib/libc/   (props changed)
  stable/9/lib/libc/stdtime/   (props changed)

Modified: stable/9/lib/libc/stdtime/strptime.c
==============================================================================
--- stable/9/lib/libc/stdtime/strptime.c	Wed Sep 28 20:52:58 2016	(r306415)
+++ stable/9/lib/libc/stdtime/strptime.c	Wed Sep 28 20:54:47 2016	(r306416)
@@ -301,10 +301,11 @@ label:
 			 * XXX This is bogus if parsed before hour-related
 			 * specifiers.
 			 */
+			if (tm->tm_hour > 12)
+				return (NULL);
+
 			len = strlen(tptr->am);
 			if (strncasecmp_l(buf, tptr->am, len, locale) == 0) {
-				if (tm->tm_hour > 12)
-					return (NULL);
 				if (tm->tm_hour == 12)
 					tm->tm_hour = 0;
 				buf += len;
@@ -313,8 +314,6 @@ label:
 
 			len = strlen(tptr->pm);
 			if (strncasecmp_l(buf, tptr->pm, len, locale) == 0) {
-				if (tm->tm_hour > 12)
-					return (NULL);
 				if (tm->tm_hour != 12)
 					tm->tm_hour += 12;
 				buf += len;
@@ -374,15 +373,17 @@ label:
 
 			break;
 
+		case 'u':
 		case 'w':
 			if (!isdigit_l((unsigned char)*buf, locale))
 				return (NULL);
 
-			i = *buf - '0';
-			if (i > 6)
+			i = *buf++ - '0';
+			if (i < 0 || i > 7 || (c == 'u' && i < 1) ||
+			    (c == 'w' && i > 6))
 				return (NULL);
 
-			tm->tm_wday = i;
+			tm->tm_wday = i % 7;
 			flags |= FLAG_WDAY;
 
 			break;
@@ -581,10 +582,16 @@ label:
 					i *= 10;
 					i += *buf - '0';
 					buf++;
+				} else if (len == 2) {
+					i *= 100;
+					break;
 				} else
 					return (NULL);
 			}
 
+			if (i > 1400 || (sign == -1 && i > 1200) ||
+			    (i % 100) >= 60)
+				return (NULL);
 			tm->tm_hour -= sign * (i / 100);
 			tm->tm_min  -= sign * (i % 100);
 			*GMTp = 1;
@@ -609,17 +616,28 @@ label:
 			    TM_YEAR_BASE)][tm->tm_mon] + (tm->tm_mday - 1);
 			flags |= FLAG_YDAY;
 		} else if (day_offset != -1) {
+			int tmpwday, tmpyday, fwo;
+
+			fwo = first_wday_of(tm->tm_year + TM_YEAR_BASE);
+			/* No incomplete week (week 0). */
+			if (week_offset == 0 && fwo == day_offset)
+				return (NULL);
+
 			/* Set the date to the first Sunday (or Monday)
 			 * of the specified week of the year.
 			 */
-			if (!(flags & FLAG_WDAY)) {
-				tm->tm_wday = day_offset;
-				flags |= FLAG_WDAY;
-			}
-			tm->tm_yday = (7 -
-			    first_wday_of(tm->tm_year + TM_YEAR_BASE) +
-			    day_offset) % 7 + (week_offset - 1) * 7 +
-			    tm->tm_wday - day_offset;
+			tmpwday = (flags & FLAG_WDAY) ? tm->tm_wday :
+			    day_offset;
+			tmpyday = (7 - fwo + day_offset) % 7 +
+			    (week_offset - 1) * 7 +
+			    (tmpwday - day_offset + 7) % 7;
+			/* Impossible yday for incomplete week (week 0). */
+			if (tmpyday < 0) {
+				if (flags & FLAG_WDAY)
+					return (NULL);
+				tmpyday = 0;
+			}
+			tm->tm_yday = tmpyday;
 			flags |= FLAG_YDAY;
 		}
 	}


More information about the svn-src-all mailing list