Bug Summary

File:d/httptime.c
Warning:line 191, column 13
Duplicate code detected
Note:line 236, column 9
Similar code here

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name httptime.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 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/isvv/naviserver/nsd -resource-dir /usr/local/lib/clang/15.0.0 -D _FORTIFY_SOURCE=2 -D NDEBUG -D SYSTEM_MALLOC -I ../include -I /usr/include/tcl8.6 -D HAVE_CONFIG_H -internal-isystem /usr/local/lib/clang/15.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/11/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -std=c99 -fdebug-compilation-dir=/home/isvv/naviserver/nsd -ferror-limit 19 -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-checker alpha -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-07-23-130959-11103-1 -x c httptime.c
1/*
2 * The contents of this file are subject to the Mozilla Public License
3 * Version 1.1 (the "License"); you may not use this file except in
4 * compliance with the License. You may obtain a copy of the License at
5 * http://mozilla.org/.
6 *
7 * Software distributed under the License is distributed on an "AS IS"
8 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9 * the License for the specific language governing rights and limitations
10 * under the License.
11 *
12 * The Original Code is AOLserver Code and related documentation
13 * distributed by AOL.
14 *
15 * The Initial Developer of the Original Code is America Online,
16 * Inc. Portions created by AOL are Copyright (C) 1999 America Online,
17 * Inc. All Rights Reserved.
18 *
19 * Alternatively, the contents of this file may be used under the terms
20 * of the GNU General Public License (the "GPL"), in which case the
21 * provisions of GPL are applicable instead of those above. If you wish
22 * to allow use of your version of this file only under the terms of the
23 * GPL and not to allow others to use your version of this file under the
24 * License, indicate your decision by deleting the provisions above and
25 * replace them with the notice and other provisions required by the GPL.
26 * If you do not delete the provisions above, a recipient may use your
27 * version of this file under either the License or the GPL.
28 */
29
30
31/*
32 * httptime.c --
33 *
34 * Manipulate times and dates; this is strongly influenced
35 * by HTSUtils.c from CERN. See also RFC 1123.
36 */
37
38#include "nsd.h"
39
40/*
41 * Local functions defined in this file
42 */
43
44static int MakeNum(const char *s)
45 NS_GNUC_NONNULL(1)__attribute__((__nonnull__(1)));
46
47static int MakeMonth(const char *s)
48 NS_GNUC_NONNULL(1)__attribute__((__nonnull__(1)));
49
50
51/*
52 * Static variables defined in this file
53 */
54
55static const char *const month_names[] = {
56 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
57 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
58};
59
60static const char *const week_names[] = {
61 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
62};
63
64#ifdef HAVE_TIMEGM1
65static Ns_Mutex lock;
66#endif
67
68
69/*
70 *----------------------------------------------------------------------
71 *
72 * Ns_Httptime --
73 *
74 * Convert a time_t into a time/date format used in HTTP
75 * (see RFC 1123). If passed-in time is null, then the
76 * current time will be used.
77 *
78 * Results:
79 * The string time, or NULL if error.
80 *
81 * Side effects:
82 * None.
83 *
84 *----------------------------------------------------------------------
85 */
86
87char *
88Ns_HttpTime(Ns_DStringTcl_DString *dsPtr, const time_t *when)
89{
90 time_t now;
91 const struct tm *tmPtr;
92 char *result = NULL((void*)0);
93
94 NS_NONNULL_ASSERT(dsPtr != NULL)((void) (0));
95
96 if (when == NULL((void*)0)) {
97 now = time(NULL((void*)0));
98 when = &now;
99 }
100 tmPtr = ns_gmtime(when);
101 if (likely(tmPtr != NULL)(__builtin_expect((tmPtr != ((void*)0)), 1))) {
102
103 /*
104 * The format is RFC 1123 "Sun, 06 Nov 1997 09:12:45 GMT"
105 * and is locale independent, so English week and month names
106 * must always be used.
107 */
108
109 Ns_DStringPrintf(dsPtr, "%s, %02d %s %d %02d:%02d:%02d GMT",
110 week_names[tmPtr->tm_wday], tmPtr->tm_mday,
111 month_names[tmPtr->tm_mon], tmPtr->tm_year + 1900,
112 tmPtr->tm_hour, tmPtr->tm_min, tmPtr->tm_sec);
113 result = dsPtr->string;
114 }
115
116 return result;
117}
118
119
120/*
121 *----------------------------------------------------------------------
122 *
123 * Ns_ParseHttpTime --
124 *
125 * Take a time in one of three formats and convert it to a time_t.
126 * Formats are: "Thursday, 10-Jun-93 01:29:59 GMT", "Thu, 10
127 * Jan 1993 01:29:59 GMT", or "Wed Jun 9 01:29:59 1993 GMT"
128 *
129 * Results:
130 * Standard time_t or 0 on error.
131 *
132 * Side effects:
133 * Unable to parse the Unix epoch because result is 0.
134 *
135 *----------------------------------------------------------------------
136 */
137
138time_t
139Ns_ParseHttpTime(const char *chars)
140{
141 const char *s;
142 struct tm timeInfo;
143 time_t t = 0;
144
145 NS_NONNULL_ASSERT(chars != NULL)((void) (0));
146
147 /*
148 * Find the comma after day-of-week
149 *
150 * Thursday, 10-Jun-93 01:29:59 GMT
151 * ^
152 * +-- s
153 *
154 * Thu, 10 Jan 1993 01:29:59 GMT
155 * ^
156 * +-- s
157 */
158
159 s = strchr(chars, INTCHAR(',')((int)((unsigned char)((',')))));
160 if (s != NULL((void*)0)) {
161
162 /*
163 * Advance S to the first non-space after the comma
164 * which should be the first digit of the day.
165 */
166
167 s++;
168 while (*s == ' ') {
169 s++;
170 }
171
172 /*
173 * Figure out which format it is in. If there is a hyphen, then
174 * it must be the first format.
175 */
176
177 if (strchr(s, INTCHAR('-')((int)((unsigned char)(('-'))))) != NULL((void*)0)) {
178 if (strlen(s) < 18u) {
179 return 0;
180 }
181
182 /*
183 * The format is:
184 *
185 * Thursday, 10-Jun-93 01:29:59 GMT
186 * ^
187 * +--s
188 */
189
190 timeInfo.tm_mday = MakeNum(s);
191 timeInfo.tm_mon = MakeMonth(s + 3);
Duplicate code detected
192 timeInfo.tm_year = MakeNum(s + 7);
193 timeInfo.tm_hour = MakeNum(s + 10);
194 timeInfo.tm_min = MakeNum(s + 13);
195 timeInfo.tm_sec = MakeNum(s + 16);
196 } else {
197 int century;
198 if ((int) strlen(s) < 20) {
199 return 0;
200 }
201
202 /*
203 * The format is:
204 *
205 * Thu, 10 Jan 1993 01:29:59 GMT
206 * ^
207 * +--s
208 */
209
210 timeInfo.tm_mday = MakeNum(s);
211 timeInfo.tm_mon = MakeMonth(s + 3);
212 century = ((100 * MakeNum(s + 7)) - 1900);
213 timeInfo.tm_year = century + MakeNum(s + 9);
214 timeInfo.tm_hour = MakeNum(s + 12);
215 timeInfo.tm_min = MakeNum(s + 15);
216 timeInfo.tm_sec = MakeNum(s + 18);
217 }
218 } else {
219
220 /*
221 * No commas, so it must be the third, fixed field, format:
222 *
223 * Wed Jun 9 01:29:59 1993 GMT
224 *
225 * Advance s to the first letter of the month.
226 */
227
228 s = chars;
229 while (*s == ' ') {
230 s++;
231 }
232 if ((int) strlen(s) < 24) {
233 return 0;
234 }
235 timeInfo.tm_mday = MakeNum(s + 8);
236 timeInfo.tm_mon = MakeMonth(s + 4);
Similar code here
237 timeInfo.tm_year = MakeNum(s + 22);
238 timeInfo.tm_hour = MakeNum(s + 11);
239 timeInfo.tm_min = MakeNum(s + 14);
240 timeInfo.tm_sec = MakeNum(s + 17);
241 }
242
243 /*
244 * If there are any impossible values, then return 0.
245 */
246
247 if (!(timeInfo.tm_sec < 0 || timeInfo.tm_sec > 59 ||
248 timeInfo.tm_min < 0 || timeInfo.tm_min > 59 ||
249 timeInfo.tm_hour < 0 || timeInfo.tm_hour > 23 ||
250 timeInfo.tm_mday < 1 || timeInfo.tm_mday > 31 ||
251 timeInfo.tm_mon < 0 || timeInfo.tm_mon > 11 ||
252 timeInfo.tm_year < 70)) {
253
254 timeInfo.tm_isdst = 0;
255#ifdef HAVE_TIMEGM1
256 /*
257 * Initialize the mutex (if this did not happen so far) and
258 * provide a name for it.
259 */
260 if (lock == NULL((void*)0)) {
261 Ns_MasterLock();
262 if (lock == NULL((void*)0)) {
263 Ns_MutexInit(&lock);
264 Ns_MutexSetName2(&lock, "ns:httptime", NULL((void*)0));
265 }
266 Ns_MasterUnlock();
267 }
268 Ns_MutexLock(&lock);
269 t = timegm(&timeInfo);
270 Ns_MutexUnlock(&lock);
271#else
272 t = mktime(&timeInfo) - timezone;
273#endif
274 }
275 return t;
276}
277
278
279/*
280 *----------------------------------------------------------------------
281 *
282 * NsTclParseHttpTimeObjCmd --
283 *
284 * Implements "ns_parsehttptime".
285 *
286 * Results:
287 * Tcl result.
288 *
289 * Side effects:
290 * Day and month names may have capitalization bashed.
291 *
292 *----------------------------------------------------------------------
293 */
294
295int
296NsTclParseHttpTimeObjCmd(ClientData UNUSED(clientData)UNUSED_clientData __attribute__((__unused__)), Tcl_Interp *interp, int objc, Tcl_Obj *const* objv)
297{
298 int result = TCL_OK0;
299 char *timeString;
300 Ns_ObjvSpec args[] = {
301 {"httptime", Ns_ObjvString, &timeString, NULL((void*)0)},
302 {NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)}
303 };
304
305 if (Ns_ParseObjv(NULL((void*)0), args, interp, 1, objc, objv) != NS_OK) {
306 result = TCL_ERROR1;
307
308 } else {
309 time_t t = Ns_ParseHttpTime(timeString);
310
311 if (likely(t != 0)(__builtin_expect((t != 0), 1))) {
312 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(t));
313 } else {
314 Ns_TclPrintfResult(interp, "invalid time: %s", timeString);
315 result = TCL_ERROR1;
316 }
317
318 }
319
320 return result;
321}
322
323
324/*
325 *----------------------------------------------------------------------
326 *
327 * NsTclHttpTimeObjCmd --
328 *
329 * Implements "ns_httptime".
330 *
331 * Results:
332 * Tcl result.
333 *
334 * Side effects:
335 * See docs.
336 *
337 *----------------------------------------------------------------------
338 */
339
340int
341NsTclHttpTimeObjCmd(ClientData UNUSED(clientData)UNUSED_clientData __attribute__((__unused__)), Tcl_Interp *interp, int objc, Tcl_Obj *const* objv)
342{
343 int result = TCL_OK0, itime = 0;
344 Ns_ObjvSpec args[] = {
345 {"time", Ns_ObjvInt, &itime, NULL((void*)0)},
346 {NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0)}
347 };
348
349 if (Ns_ParseObjv(NULL((void*)0), args, interp, 1, objc, objv) != NS_OK) {
350 result = TCL_ERROR1;
351
352 } else {
353 Ns_DStringTcl_DString ds;
354 time_t t = (time_t) itime;
355
356 Ns_DStringInitTcl_DStringInit(&ds);
357 (void) Ns_HttpTime(&ds, &t);
358 Tcl_DStringResult(interp, &ds);
359 }
360
361 return result;
362}
363
364
365/*
366 *----------------------------------------------------------------------
367 *
368 * MakeNum --
369 *
370 * Convert a one or two-digit day into an integer, allowing a
371 * space in the first position.
372 *
373 * Results:
374 * An integer.
375 *
376 * Side effects:
377 * None.
378 *
379 *----------------------------------------------------------------------
380 */
381
382static int
383MakeNum(const char *s)
384{
385 int result;
386
387 NS_NONNULL_ASSERT(s != NULL)((void) (0));
388
389 if (CHARTYPE(digit, *s)(((*__ctype_b_loc ())[(int) (((int)((unsigned char)(*s))))] &
(unsigned short int) _ISdigit))
!= 0) {
390 result = (10 * ((int)UCHAR(*s)((unsigned char)(*s)) - (int)UCHAR('0')((unsigned char)('0')))) + ((int)UCHAR(*(s + 1))((unsigned char)(*(s + 1))) - (int)UCHAR('0')((unsigned char)('0')));
391 } else {
392 result = (int)UCHAR(*(s + 1))((unsigned char)(*(s + 1))) - (int)UCHAR('0')((unsigned char)('0'));
393 }
394 return result;
395}
396
397
398/*
399 *----------------------------------------------------------------------
400 *
401 * MakeMonth --
402 *
403 * Convert a three-digit abbreviated month name into a number;
404 * e.g., Jan=0, Feb=1, etc.
405 *
406 * Results:
407 * An integral month number.
408 *
409 * Side effects:
410 * Changes passed string to camel case.
411 *
412 *----------------------------------------------------------------------
413 */
414
415static int
416MakeMonth(const char *s)
417{
418 int i, result = 0;
419
420 NS_NONNULL_ASSERT(s != NULL)((void) (0));
421
422 /*
423 * Make sure it is capitalized like this:
424 * "Jan"
425 */
426
427 for (i = 0; i < 12; i++) {
428 if (strncasecmp(month_names[i], s, 3u) == 0) {
429 result = i;
430 break;
431 }
432 }
433
434 return result;
435}
436
437/*
438 * Local Variables:
439 * mode: c
440 * c-basic-offset: 4
441 * fill-column: 78
442 * indent-tabs-mode: nil
443 * End:
444 */