Bug Summary

File:src/lib/libc/time/strptime.c
Warning:line 577, column 45
The right operand of '>=' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name strptime.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/lib/libc/obj -resource-dir /usr/local/lib/clang/13.0.0 -include namespace.h -I /usr/src/lib/libc/include -I /usr/src/lib/libc/hidden -D __LIBC__ -D APIWARN -D YP -I /usr/src/lib/libc/yp -I /usr/src/lib/libc -I /usr/src/lib/libc/gdtoa -I /usr/src/lib/libc/arch/amd64/gdtoa -D INFNAN_CHECK -D MULTIPLE_THREADS -D NO_FENV_H -D USE_LOCALE -I /usr/src/lib/libc -I /usr/src/lib/libc/citrus -D RESOLVSORT -D FLOATING_POINT -D PRINTF_WIDE_CHAR -D SCANF_WIDE_CHAR -D FUTEX -D PIC -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/lib/libc/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/lib/libc/time/strptime.c
1/* $OpenBSD: strptime.c,v 1.30 2019/05/12 12:49:52 schwarze Exp $ */
2/* $NetBSD: strptime.c,v 1.12 1998/01/20 21:39:40 mycroft Exp $ */
3/*-
4 * Copyright (c) 1997, 1998, 2005, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code was contributed to The NetBSD Foundation by Klaus Klein.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <ctype.h>
32#include <locale.h>
33#include <stdint.h>
34#include <string.h>
35#include <time.h>
36
37#include "localedef.h"
38#include "private.h"
39#include "tzfile.h"
40
41#define _ctloc(x)(_CurrentTimeLocale->x) (_CurrentTimeLocale->x)
42
43/*
44 * We do not implement alternate representations. However, we always
45 * check whether a given modifier is allowed for a certain conversion.
46 */
47#define _ALT_E0x01 0x01
48#define _ALT_O0x02 0x02
49#define _LEGAL_ALT(x){ if (alt_format & ~(x)) return (0); } { if (alt_format & ~(x)) return (0); }
50
51/*
52 * We keep track of some of the fields we set in order to compute missing ones.
53 */
54#define FIELD_TM_MON(1 << 0) (1 << 0)
55#define FIELD_TM_MDAY(1 << 1) (1 << 1)
56#define FIELD_TM_WDAY(1 << 2) (1 << 2)
57#define FIELD_TM_YDAY(1 << 3) (1 << 3)
58#define FIELD_TM_YEAR(1 << 4) (1 << 4)
59
60static char gmt[] = { "GMT" };
61static char utc[] = { "UTC" };
62/* RFC-822/RFC-2822 */
63static const char * const nast[5] = {
64 "EST", "CST", "MST", "PST", "\0\0\0"
65};
66static const char * const nadt[5] = {
67 "EDT", "CDT", "MDT", "PDT", "\0\0\0"
68};
69
70static const int mon_lengths[2][MONSPERYEAR12] = {
71 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
72 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
73};
74
75static int _conv_num64(const unsigned char **, int64_t *, int64_t, int64_t);
76static int _conv_num(const unsigned char **, int *, int, int);
77static int leaps_thru_end_of(const int y);
78static char *_strptime(const char *, const char *, struct tm *, int);
79static const u_char *_find_string(const u_char *, int *, const char * const *,
80 const char * const *, int);
81
82
83char *
84strptime(const char *buf, const char *fmt, struct tm *tm)
85{
86 return(_strptime(buf, fmt, tm, 1));
87}
88DEF_WEAK(strptime)__asm__(".weak " "strptime" " ; " "strptime" " = " "_libc_strptime"
)
;
89
90static char *
91_strptime(const char *buf, const char *fmt, struct tm *tm, int initialize)
92{
93 unsigned char c;
94 const unsigned char *bp, *ep;
95 size_t len;
96 int alt_format, i, offs;
97 int neg = 0;
98 static int century, relyear, fields;
99
100 if (initialize) {
1
Assuming 'initialize' is 0
2
Taking false branch
101 century = TM_YEAR_BASE1900;
102 relyear = -1;
103 fields = 0;
104 }
105
106 bp = (const unsigned char *)buf;
107 while ((c = *fmt) != '\0') {
3
Assuming the condition is true
4
Loop condition is true. Entering loop body
22
Assuming the condition is false
23
Loop condition is false. Execution continues on line 539
108 /* Clear `alternate' modifier prior to new conversion. */
109 alt_format = 0;
110
111 /* Eat up white-space. */
112 if (isspace(c)) {
5
Taking false branch
113 while (isspace(*bp))
114 bp++;
115
116 fmt++;
117 continue;
118 }
119
120 if ((c = *fmt++) != '%')
6
Assuming the condition is false
7
Taking false branch
121 goto literal;
122
123
124again: switch (c = *fmt++) {
8
Control jumps to 'case 106:' at line 286
125 case '%': /* "%%" is converted to "%". */
126literal:
127 if (c != *bp++)
128 return (NULL((void *)0));
129
130 break;
131
132 /*
133 * "Alternative" modifiers. Just set the appropriate flag
134 * and start over again.
135 */
136 case 'E': /* "%E?" alternative conversion modifier. */
137 _LEGAL_ALT(0){ if (alt_format & ~(0)) return (0); };
138 alt_format |= _ALT_E0x01;
139 goto again;
140
141 case 'O': /* "%O?" alternative conversion modifier. */
142 _LEGAL_ALT(0){ if (alt_format & ~(0)) return (0); };
143 alt_format |= _ALT_O0x02;
144 goto again;
145
146 /*
147 * "Complex" conversion rules, implemented through recursion.
148 */
149 case 'c': /* Date and time, using the locale's format. */
150 _LEGAL_ALT(_ALT_E){ if (alt_format & ~(0x01)) return (0); };
151 if (!(bp = _strptime(bp, _ctloc(d_t_fmt)(_CurrentTimeLocale->d_t_fmt), tm, 0)))
152 return (NULL((void *)0));
153 break;
154
155 case 'D': /* The date as "%m/%d/%y". */
156 _LEGAL_ALT(0){ if (alt_format & ~(0)) return (0); };
157 if (!(bp = _strptime(bp, "%m/%d/%y", tm, 0)))
158 return (NULL((void *)0));
159 break;
160
161 case 'F': /* The date as "%Y-%m-%d". */
162 _LEGAL_ALT(0){ if (alt_format & ~(0)) return (0); };
163 if (!(bp = _strptime(bp, "%Y-%m-%d", tm, 0)))
164 return (NULL((void *)0));
165 continue;
166
167 case 'R': /* The time as "%H:%M". */
168 _LEGAL_ALT(0){ if (alt_format & ~(0)) return (0); };
169 if (!(bp = _strptime(bp, "%H:%M", tm, 0)))
170 return (NULL((void *)0));
171 break;
172
173 case 'r': /* The time as "%I:%M:%S %p". */
174 _LEGAL_ALT(0){ if (alt_format & ~(0)) return (0); };
175 if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, 0)))
176 return (NULL((void *)0));
177 break;
178
179 case 'T': /* The time as "%H:%M:%S". */
180 _LEGAL_ALT(0){ if (alt_format & ~(0)) return (0); };
181 if (!(bp = _strptime(bp, "%H:%M:%S", tm, 0)))
182 return (NULL((void *)0));
183 break;
184
185 case 'X': /* The time, using the locale's format. */
186 _LEGAL_ALT(_ALT_E){ if (alt_format & ~(0x01)) return (0); };
187 if (!(bp = _strptime(bp, _ctloc(t_fmt)(_CurrentTimeLocale->t_fmt), tm, 0)))
188 return (NULL((void *)0));
189 break;
190
191 case 'x': /* The date, using the locale's format. */
192 _LEGAL_ALT(_ALT_E){ if (alt_format & ~(0x01)) return (0); };
193 if (!(bp = _strptime(bp, _ctloc(d_fmt)(_CurrentTimeLocale->d_fmt), tm, 0)))
194 return (NULL((void *)0));
195 break;
196
197 /*
198 * "Elementary" conversion rules.
199 */
200 case 'A': /* The day of week, using the locale's form. */
201 case 'a':
202 _LEGAL_ALT(0){ if (alt_format & ~(0)) return (0); };
203 for (i = 0; i < 7; i++) {
204 /* Full name. */
205 len = strlen(_ctloc(day[i])(_CurrentTimeLocale->day[i]));
206 if (strncasecmp(_ctloc(day[i])(_CurrentTimeLocale->day[i]), bp, len) == 0)
207 break;
208
209 /* Abbreviated name. */
210 len = strlen(_ctloc(abday[i])(_CurrentTimeLocale->abday[i]));
211 if (strncasecmp(_ctloc(abday[i])(_CurrentTimeLocale->abday[i]), bp, len) == 0)
212 break;
213 }
214
215 /* Nothing matched. */
216 if (i == 7)
217 return (NULL((void *)0));
218
219 tm->tm_wday = i;
220 bp += len;
221 fields |= FIELD_TM_WDAY(1 << 2);
222 break;
223
224 case 'B': /* The month, using the locale's form. */
225 case 'b':
226 case 'h':
227 _LEGAL_ALT(0){ if (alt_format & ~(0)) return (0); };
228 for (i = 0; i < 12; i++) {
229 /* Full name. */
230 len = strlen(_ctloc(mon[i])(_CurrentTimeLocale->mon[i]));
231 if (strncasecmp(_ctloc(mon[i])(_CurrentTimeLocale->mon[i]), bp, len) == 0)
232 break;
233
234 /* Abbreviated name. */
235 len = strlen(_ctloc(abmon[i])(_CurrentTimeLocale->abmon[i]));
236 if (strncasecmp(_ctloc(abmon[i])(_CurrentTimeLocale->abmon[i]), bp, len) == 0)
237 break;
238 }
239
240 /* Nothing matched. */
241 if (i == 12)
242 return (NULL((void *)0));
243
244 tm->tm_mon = i;
245 bp += len;
246 fields |= FIELD_TM_MON(1 << 0);
247 break;
248
249 case 'C': /* The century number. */
250 _LEGAL_ALT(_ALT_E){ if (alt_format & ~(0x01)) return (0); };
251 if (!(_conv_num(&bp, &i, 0, 99)))
252 return (NULL((void *)0));
253
254 century = i * 100;
255 break;
256
257 case 'e': /* The day of month. */
258 if (isspace(*bp))
259 bp++;
260 /* FALLTHROUGH */
261 case 'd':
262 _LEGAL_ALT(_ALT_O){ if (alt_format & ~(0x02)) return (0); };
263 if (!(_conv_num(&bp, &tm->tm_mday, 1, 31)))
264 return (NULL((void *)0));
265 fields |= FIELD_TM_MDAY(1 << 1);
266 break;
267
268 case 'k': /* The hour (24-hour clock representation). */
269 _LEGAL_ALT(0){ if (alt_format & ~(0)) return (0); };
270 /* FALLTHROUGH */
271 case 'H':
272 _LEGAL_ALT(_ALT_O){ if (alt_format & ~(0x02)) return (0); };
273 if (!(_conv_num(&bp, &tm->tm_hour, 0, 23)))
274 return (NULL((void *)0));
275 break;
276
277 case 'l': /* The hour (12-hour clock representation). */
278 _LEGAL_ALT(0){ if (alt_format & ~(0)) return (0); };
279 /* FALLTHROUGH */
280 case 'I':
281 _LEGAL_ALT(_ALT_O){ if (alt_format & ~(0x02)) return (0); };
282 if (!(_conv_num(&bp, &tm->tm_hour, 1, 12)))
283 return (NULL((void *)0));
284 break;
285
286 case 'j': /* The day of year. */
287 _LEGAL_ALT(0){ if (alt_format & ~(0)) return (0); };
9
Taking false branch
288 if (!(_conv_num(&bp, &tm->tm_yday, 1, 366)))
10
Calling '_conv_num'
19
Returning from '_conv_num'
20
Taking false branch
289 return (NULL((void *)0));
290 tm->tm_yday--;
291 fields |= FIELD_TM_YDAY(1 << 3);
292 break;
21
Execution continues on line 107
293
294 case 'M': /* The minute. */
295 _LEGAL_ALT(_ALT_O){ if (alt_format & ~(0x02)) return (0); };
296 if (!(_conv_num(&bp, &tm->tm_min, 0, 59)))
297 return (NULL((void *)0));
298 break;
299
300 case 'm': /* The month. */
301 _LEGAL_ALT(_ALT_O){ if (alt_format & ~(0x02)) return (0); };
302 if (!(_conv_num(&bp, &tm->tm_mon, 1, 12)))
303 return (NULL((void *)0));
304 tm->tm_mon--;
305 fields |= FIELD_TM_MON(1 << 0);
306 break;
307
308 case 'p': /* The locale's equivalent of AM/PM. */
309 _LEGAL_ALT(0){ if (alt_format & ~(0)) return (0); };
310 /* AM? */
311 len = strlen(_ctloc(am_pm[0])(_CurrentTimeLocale->am_pm[0]));
312 if (strncasecmp(_ctloc(am_pm[0])(_CurrentTimeLocale->am_pm[0]), bp, len) == 0) {
313 if (tm->tm_hour > 12) /* i.e., 13:00 AM ?! */
314 return (NULL((void *)0));
315 else if (tm->tm_hour == 12)
316 tm->tm_hour = 0;
317
318 bp += len;
319 break;
320 }
321 /* PM? */
322 len = strlen(_ctloc(am_pm[1])(_CurrentTimeLocale->am_pm[1]));
323 if (strncasecmp(_ctloc(am_pm[1])(_CurrentTimeLocale->am_pm[1]), bp, len) == 0) {
324 if (tm->tm_hour > 12) /* i.e., 13:00 PM ?! */
325 return (NULL((void *)0));
326 else if (tm->tm_hour < 12)
327 tm->tm_hour += 12;
328
329 bp += len;
330 break;
331 }
332
333 /* Nothing matched. */
334 return (NULL((void *)0));
335
336 case 'S': /* The seconds. */
337 _LEGAL_ALT(_ALT_O){ if (alt_format & ~(0x02)) return (0); };
338 if (!(_conv_num(&bp, &tm->tm_sec, 0, 60)))
339 return (NULL((void *)0));
340 break;
341 case 's': /* Seconds since epoch */
342 {
343 int64_t i64;
344 if (!(_conv_num64(&bp, &i64, 0, INT64_MAX0x7fffffffffffffffLL)))
345 return (NULL((void *)0));
346 if (!gmtime_r(&i64, tm))
347 return (NULL((void *)0));
348 fields = 0xffff; /* everything */
349 }
350 break;
351 case 'U': /* The week of year, beginning on sunday. */
352 case 'W': /* The week of year, beginning on monday. */
353 _LEGAL_ALT(_ALT_O){ if (alt_format & ~(0x02)) return (0); };
354 /*
355 * XXX This is bogus, as we can not assume any valid
356 * information present in the tm structure at this
357 * point to calculate a real value, so just check the
358 * range for now.
359 */
360 if (!(_conv_num(&bp, &i, 0, 53)))
361 return (NULL((void *)0));
362 break;
363
364 case 'w': /* The day of week, beginning on sunday. */
365 _LEGAL_ALT(_ALT_O){ if (alt_format & ~(0x02)) return (0); };
366 if (!(_conv_num(&bp, &tm->tm_wday, 0, 6)))
367 return (NULL((void *)0));
368 fields |= FIELD_TM_WDAY(1 << 2);
369 break;
370
371 case 'u': /* The day of week, monday = 1. */
372 _LEGAL_ALT(_ALT_O){ if (alt_format & ~(0x02)) return (0); };
373 if (!(_conv_num(&bp, &i, 1, 7)))
374 return (NULL((void *)0));
375 tm->tm_wday = i % 7;
376 fields |= FIELD_TM_WDAY(1 << 2);
377 continue;
378
379 case 'g': /* The year corresponding to the ISO week
380 * number but without the century.
381 */
382 if (!(_conv_num(&bp, &i, 0, 99)))
383 return (NULL((void *)0));
384 continue;
385
386 case 'G': /* The year corresponding to the ISO week
387 * number with century.
388 */
389 do
390 bp++;
391 while (isdigit(*bp));
392 continue;
393
394 case 'V': /* The ISO 8601:1988 week number as decimal */
395 if (!(_conv_num(&bp, &i, 0, 53)))
396 return (NULL((void *)0));
397 continue;
398
399 case 'Y': /* The year. */
400 _LEGAL_ALT(_ALT_E){ if (alt_format & ~(0x01)) return (0); };
401 if (!(_conv_num(&bp, &i, 0, 9999)))
402 return (NULL((void *)0));
403
404 relyear = -1;
405 tm->tm_year = i - TM_YEAR_BASE1900;
406 fields |= FIELD_TM_YEAR(1 << 4);
407 break;
408
409 case 'y': /* The year within the century (2 digits). */
410 _LEGAL_ALT(_ALT_E | _ALT_O){ if (alt_format & ~(0x01 | 0x02)) return (0); };
411 if (!(_conv_num(&bp, &relyear, 0, 99)))
412 return (NULL((void *)0));
413 break;
414
415 case 'Z':
416 tzset();
417 if (strncmp((const char *)bp, gmt, 3) == 0) {
418 tm->tm_isdst = 0;
419 tm->tm_gmtoff = 0;
420 tm->tm_zone = gmt;
421 bp += 3;
422 } else if (strncmp((const char *)bp, utc, 3) == 0) {
423 tm->tm_isdst = 0;
424 tm->tm_gmtoff = 0;
425 tm->tm_zone = utc;
426 bp += 3;
427 } else {
428 ep = _find_string(bp, &i,
429 (const char * const *)tzname,
430 NULL((void *)0), 2);
431 if (ep == NULL((void *)0))
432 return (NULL((void *)0));
433
434 tm->tm_isdst = i;
435 tm->tm_gmtoff = -(timezone);
436 tm->tm_zone = tzname[i];
437 bp = ep;
438 }
439 continue;
440
441 case 'z':
442 /*
443 * We recognize all ISO 8601 formats:
444 * Z = Zulu time/UTC
445 * [+-]hhmm
446 * [+-]hh:mm
447 * [+-]hh
448 * We recognize all RFC-822/RFC-2822 formats:
449 * UT|GMT
450 * North American : UTC offsets
451 * E[DS]T = Eastern : -4 | -5
452 * C[DS]T = Central : -5 | -6
453 * M[DS]T = Mountain: -6 | -7
454 * P[DS]T = Pacific : -7 | -8
455 */
456 while (isspace(*bp))
457 bp++;
458
459 switch (*bp++) {
460 case 'G':
461 if (*bp++ != 'M')
462 return NULL((void *)0);
463 /*FALLTHROUGH*/
464 case 'U':
465 if (*bp++ != 'T')
466 return NULL((void *)0);
467 /*FALLTHROUGH*/
468 case 'Z':
469 tm->tm_isdst = 0;
470 tm->tm_gmtoff = 0;
471 tm->tm_zone = utc;
472 continue;
473 case '+':
474 neg = 0;
475 break;
476 case '-':
477 neg = 1;
478 break;
479 default:
480 --bp;
481 ep = _find_string(bp, &i, nast, NULL((void *)0), 4);
482 if (ep != NULL((void *)0)) {
483 tm->tm_gmtoff = (-5 - i) * SECSPERHOUR(60 * 60);
484 tm->tm_zone = (char *)nast[i];
485 bp = ep;
486 continue;
487 }
488 ep = _find_string(bp, &i, nadt, NULL((void *)0), 4);
489 if (ep != NULL((void *)0)) {
490 tm->tm_isdst = 1;
491 tm->tm_gmtoff = (-4 - i) * SECSPERHOUR(60 * 60);
492 tm->tm_zone = (char *)nadt[i];
493 bp = ep;
494 continue;
495 }
496 return NULL((void *)0);
497 }
498 if (!isdigit(bp[0]) || !isdigit(bp[1]))
499 return NULL((void *)0);
500 offs = ((bp[0]-'0') * 10 + (bp[1]-'0')) * SECSPERHOUR(60 * 60);
501 bp += 2;
502 if (*bp == ':')
503 bp++;
504 if (isdigit(*bp)) {
505 offs += (*bp++ - '0') * 10 * SECSPERMIN60;
506 if (!isdigit(*bp))
507 return NULL((void *)0);
508 offs += (*bp++ - '0') * SECSPERMIN60;
509 }
510 if (neg)
511 offs = -offs;
512 tm->tm_isdst = 0; /* XXX */
513 tm->tm_gmtoff = offs;
514 tm->tm_zone = NULL((void *)0); /* XXX */
515 continue;
516
517 /*
518 * Miscellaneous conversions.
519 */
520 case 'n': /* Any kind of white-space. */
521 case 't':
522 _LEGAL_ALT(0){ if (alt_format & ~(0)) return (0); };
523 while (isspace(*bp))
524 bp++;
525 break;
526
527
528 default: /* Unknown/unsupported conversion. */
529 return (NULL((void *)0));
530 }
531
532
533 }
534
535 /*
536 * We need to evaluate the two digit year spec (%y)
537 * last as we can get a century spec (%C) at any time.
538 */
539 if (relyear != -1) {
24
Taking true branch
540 if (century
24.1
'century' is not equal to TM_YEAR_BASE
== TM_YEAR_BASE1900) {
25
Taking false branch
541 if (relyear <= 68)
542 tm->tm_year = relyear + 2000 - TM_YEAR_BASE1900;
543 else
544 tm->tm_year = relyear + 1900 - TM_YEAR_BASE1900;
545 } else {
546 tm->tm_year = relyear + century - TM_YEAR_BASE1900;
547 }
548 fields |= FIELD_TM_YEAR(1 << 4);
549 }
550
551 /* Compute some missing values when possible. */
552 if (fields & FIELD_TM_YEAR(1 << 4)) {
26
Taking true branch
553 const int year = tm->tm_year + TM_YEAR_BASE1900;
554 const int *mon_lens = mon_lengths[isleap(year)(((year) % 4) == 0 && (((year) % 100) != 0 || ((year)
% 400) == 0))
];
555 if (!(fields & FIELD_TM_YDAY(1 << 3)) &&
556 (fields & FIELD_TM_MON(1 << 0)) && (fields & FIELD_TM_MDAY(1 << 1))) {
557 tm->tm_yday = tm->tm_mday - 1;
558 for (i = 0; i < tm->tm_mon; i++)
559 tm->tm_yday += mon_lens[i];
560 fields |= FIELD_TM_YDAY(1 << 3);
561 }
562 if (fields & FIELD_TM_YDAY(1 << 3)) {
27
Taking true branch
563 int days = tm->tm_yday;
564 if (!(fields & FIELD_TM_WDAY(1 << 2))) {
28
Taking true branch
565 tm->tm_wday = EPOCH_WDAY4 +
566 ((year - EPOCH_YEAR1970) % DAYSPERWEEK7) *
567 (DAYSPERNYEAR365 % DAYSPERWEEK7) +
568 leaps_thru_end_of(year - 1) -
569 leaps_thru_end_of(EPOCH_YEAR1970 - 1) +
570 tm->tm_yday;
571 tm->tm_wday %= DAYSPERWEEK7;
572 if (tm->tm_wday < 0)
29
Assuming field 'tm_wday' is >= 0
30
Taking false branch
573 tm->tm_wday += DAYSPERWEEK7;
574 }
575 if (!(fields & FIELD_TM_MON(1 << 0))) {
31
Taking true branch
576 tm->tm_mon = 0;
32
The value 0 is assigned to field 'tm_mon'
577 while (tm->tm_mon
32.1
Field 'tm_mon' is < MONSPERYEAR
< MONSPERYEAR12 && days >= mon_lens[tm->tm_mon])
33
The right operand of '>=' is a garbage value
578 days -= mon_lens[tm->tm_mon++];
579 }
580 if (!(fields & FIELD_TM_MDAY(1 << 1)))
581 tm->tm_mday = days + 1;
582 }
583 }
584
585 return ((char *)bp);
586}
587
588
589static int
590_conv_num(const unsigned char **buf, int *dest, int llim, int ulim)
591{
592 int result = 0;
593 int rulim = ulim;
594
595 if (**buf < '0' || **buf > '9')
11
Assuming the condition is false
12
Assuming the condition is false
13
Taking false branch
596 return (0);
597
598 /* we use rulim to break out of the loop when we run out of digits */
599 do {
15
Loop condition is false. Exiting loop
600 result *= 10;
601 result += *(*buf)++ - '0';
602 rulim /= 10;
603 } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
14
Assuming the condition is false
604
605 if (result < llim || result
16.1
'result' is <= 'ulim'
> ulim)
16
Assuming 'result' is >= 'llim'
17
Taking false branch
606 return (0);
607
608 *dest = result;
609 return (1);
18
Returning the value 1, which participates in a condition later
610}
611
612static int
613_conv_num64(const unsigned char **buf, int64_t *dest, int64_t llim, int64_t ulim)
614{
615 int result = 0;
616 int64_t rulim = ulim;
617
618 if (**buf < '0' || **buf > '9')
619 return (0);
620
621 /* we use rulim to break out of the loop when we run out of digits */
622 do {
623 result *= 10;
624 result += *(*buf)++ - '0';
625 rulim /= 10;
626 } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
627
628 if (result < llim || result > ulim)
629 return (0);
630
631 *dest = result;
632 return (1);
633}
634
635static const u_char *
636_find_string(const u_char *bp, int *tgt, const char * const *n1,
637 const char * const *n2, int c)
638{
639 int i;
640 unsigned int len;
641
642 /* check full name - then abbreviated ones */
643 for (; n1 != NULL((void *)0); n1 = n2, n2 = NULL((void *)0)) {
644 for (i = 0; i < c; i++, n1++) {
645 len = strlen(*n1);
646 if (strncasecmp(*n1, (const char *)bp, len) == 0) {
647 *tgt = i;
648 return bp + len;
649 }
650 }
651 }
652
653 /* Nothing matched */
654 return NULL((void *)0);
655}
656
657static int
658leaps_thru_end_of(const int y)
659{
660 return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
661 -(leaps_thru_end_of(-(y + 1)) + 1);
662}