summaryrefslogtreecommitdiffstats
path: root/lib/libc
diff options
context:
space:
mode:
authorache <ache@FreeBSD.org>2016-09-28 20:52:58 +0000
committerache <ache@FreeBSD.org>2016-09-28 20:52:58 +0000
commit7f3b434135c0226b3f1247c2cd4d3ce472a406fc (patch)
treef895f250482c5db26a18da87ec3ab18122155b80 /lib/libc
parent287376aa3f49ff4ad12d60f352e461f58d0a1a2a (diff)
downloadFreeBSD-src-7f3b434135c0226b3f1247c2cd4d3ce472a406fc.zip
FreeBSD-src-7f3b434135c0226b3f1247c2cd4d3ce472a406fc.tar.gz
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)
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/stdtime/strptime.c46
1 files changed, 32 insertions, 14 deletions
diff --git a/lib/libc/stdtime/strptime.c b/lib/libc/stdtime/strptime.c
index 2be6358..89703ec 100644
--- a/lib/libc/stdtime/strptime.c
+++ b/lib/libc/stdtime/strptime.c
@@ -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;
+ 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 = (7 -
- first_wday_of(tm->tm_year + TM_YEAR_BASE) +
- day_offset) % 7 + (week_offset - 1) * 7 +
- tm->tm_wday - day_offset;
+ tm->tm_yday = tmpyday;
flags |= FLAG_YDAY;
}
}
OpenPOWER on IntegriCloud