Bug Summary

File:src/libexec/tradcpp/files.c
Warning:line 238, column 5
Value stored to 'ateof' is never read

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 files.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 -pic-is-pie -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/libexec/tradcpp/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/libexec/tradcpp/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/libexec/tradcpp/files.c
1/*-
2 * Copyright (c) 2010, 2013 The NetBSD Foundation, Inc.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by David A. Holland.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <unistd.h>
34#include <fcntl.h>
35#include <errno(*__errno()).h>
36
37#include "bool.h"
38#include "array.h"
39#include "mode.h"
40#include "place.h"
41#include "files.h"
42#include "directive.h"
43
44struct incdir {
45 const char *name;
46 bool issystem;
47};
48
49DECLARRAY(incdir, static UNUSED)struct incdirarray { struct array arr; }; static __attribute__
((__unused__)) struct incdirarray *incdirarray_create(void); static
__attribute__((__unused__)) void incdirarray_destroy(struct incdirarray
*a); static __attribute__((__unused__)) void incdirarray_init
(struct incdirarray *a); static __attribute__((__unused__)) void
incdirarray_cleanup(struct incdirarray *a); static __attribute__
((__unused__)) unsigned incdirarray_num(const struct incdirarray
*a); static __attribute__((__unused__)) struct incdir *incdirarray_get
(const struct incdirarray *a, unsigned index_); static __attribute__
((__unused__)) void incdirarray_set(struct incdirarray *a, unsigned
index_, struct incdir *val); static __attribute__((__unused__
)) void incdirarray_setsize(struct incdirarray *a, unsigned num
); static __attribute__((__unused__)) void incdirarray_add(struct
incdirarray *a, struct incdir *val, unsigned *index_ret); static
__attribute__((__unused__)) void incdirarray_insert(struct incdirarray
*a, unsigned index_); static __attribute__((__unused__)) void
incdirarray_remove(struct incdirarray *a, unsigned index_)
;
50DEFARRAY(incdir, static)static void incdirarray_init(struct incdirarray *a) { array_init
(&a->arr); } static void incdirarray_cleanup(struct incdirarray
*a) { array_cleanup(&a->arr); } static struct incdirarray
*incdirarray_create(void) { struct incdirarray *a; a = domalloc
(sizeof(*a)); incdirarray_init(a); return a; } static void incdirarray_destroy
(struct incdirarray *a) { incdirarray_cleanup(a); dofree(a, sizeof
(*a)); } static unsigned incdirarray_num(const struct incdirarray
*a) { return array_num(&a->arr); } static struct incdir
* incdirarray_get(const struct incdirarray *a, unsigned index_
) { return (struct incdir *)array_get(&a->arr, index_)
; } static void incdirarray_set(struct incdirarray *a, unsigned
index_, struct incdir *val) { array_set(&a->arr, index_
, (void *)val); } static void incdirarray_setsize(struct incdirarray
*a, unsigned num) { array_setsize(&a->arr, num); } static
void incdirarray_add(struct incdirarray *a, struct incdir *val
, unsigned *ret) { array_add(&a->arr, (void *)val, ret
); } static void incdirarray_insert(struct incdirarray *a, unsigned
index_) { array_insert(&a->arr, index_); } static void
incdirarray_remove(struct incdirarray *a, unsigned index_) {
array_remove(&a->arr, index_); }
;
51
52static struct incdirarray quotepath, bracketpath;
53
54////////////////////////////////////////////////////////////
55// management
56
57static
58struct incdir *
59incdir_create(const char *name, bool issystem)
60{
61 struct incdir *id;
62
63 id = domalloc(sizeof(*id));
64 id->name = name;
65 id->issystem = issystem;
66 return id;
67}
68
69static
70void
71incdir_destroy(struct incdir *id)
72{
73 dofree(id, sizeof(*id));
74}
75
76void
77files_init(void)
78{
79 incdirarray_init(&quotepath);
80 incdirarray_init(&bracketpath);
81}
82
83DESTROYALL_ARRAY(incdir, )void incdirarray_destroyall(struct incdirarray *arr); void incdirarray_destroyall
(struct incdirarray *arr) { unsigned i, num; struct incdir *t
; num = incdirarray_num(arr); for (i=0; i<num; i++) { t = incdirarray_get
(arr, i); incdir_destroy(t); } incdirarray_setsize(arr, 0); }
;
84
85void
86files_cleanup(void)
87{
88 incdirarray_destroyall(&quotepath);
89 incdirarray_cleanup(&quotepath);
90 incdirarray_destroyall(&bracketpath);
91 incdirarray_cleanup(&bracketpath);
92}
93
94////////////////////////////////////////////////////////////
95// path setup
96
97void
98files_addquotepath(const char *dir, bool issystem)
99{
100 struct incdir *id;
101
102 id = incdir_create(dir, issystem);
103 incdirarray_add(&quotepath, id, NULL((void*)0));
104}
105
106void
107files_addbracketpath(const char *dir, bool issystem)
108{
109 struct incdir *id;
110
111 id = incdir_create(dir, issystem);
112 incdirarray_add(&bracketpath, id, NULL((void*)0));
113}
114
115////////////////////////////////////////////////////////////
116// parsing
117
118/*
119 * Find the end of the logical line. End of line characters that are
120 * commented out do not count.
121 */
122static
123size_t
124findeol(const char *buf, size_t start, size_t limit)
125{
126 size_t i;
127 int incomment = 0;
128 bool inquote = false0;
129 char quote = '\0';
130
131 for (i=start; i<limit; i++) {
132 if (incomment) {
133 if (i+1 < limit && buf[i] == '*' && buf[i+1] == '/') {
134 i++;
135 incomment = 0;
136 }
137 } else if (!inquote && i+1 < limit &&
138 buf[i] == '/' && buf[i+1] == '*') {
139 i++;
140 incomment = 1;
141 } else if (i+1 < limit &&
142 buf[i] == '\\' && buf[i+1] != '\n') {
143 i++;
144 } else if (!inquote && (buf[i] == '"' || buf[i] == '\'')) {
145 inquote = true1;
146 quote = buf[i];
147 } else if (inquote && buf[i] == quote) {
148 inquote = false0;
149 } else if (buf[i] == '\n') {
150 return i;
151 }
152 }
153 return limit;
154}
155
156static
157unsigned
158countnls(const char *buf, size_t start, size_t limit)
159{
160 size_t i;
161 unsigned count = 0;
162
163 for (i=start; i<limit; i++) {
164 if (buf[i] == '\n') {
165 count++;
166 if (count == 0) {
167 /* just return the max and error downstream */
168 return count - 1;
169 }
170 }
171 }
172 return count;
173}
174
175static
176void
177file_read(const struct placefile *pf, int fd, const char *name, bool toplevel)
178{
179 struct lineplace places;
180 struct place ptmp;
181 size_t bufend, bufmax, linestart, lineend, nextlinestart, tmp;
182 ssize_t result;
183 bool ateof = false0;
184 char *buf;
185
186 place_setfilestart(&places.current, pf);
187 places.nextline = places.current;
188
189 if (name) {
190 debuglog(&places.current, "Reading file %s", name);
191 } else {
192 debuglog(&places.current, "Reading standard input");
193 }
194
195 bufmax = 128;
196 bufend = 0;
197 linestart = 0;
198 lineend = 0;
199 buf = domalloc(bufmax);
200
201 while (1) {
202 if (lineend >= bufend) {
203 /* do not have a whole line in the buffer; read more */
204 assert(bufend >= linestart)((bufend >= linestart) ? (void)0 : __assert2("/usr/src/libexec/tradcpp/files.c"
, 204, __func__, "bufend >= linestart"))
;
205 if (linestart > 0 && bufend > linestart) {
206 /* slide to beginning of buffer */
207 memmove(buf, buf+linestart, bufend-linestart);
208 bufend -= linestart;
209 lineend -= linestart;
210 linestart = 0;
211 }
212 if (bufend >= bufmax) {
213 /* need bigger buffer */
214 buf = dorealloc(buf, bufmax, bufmax*2);
215 bufmax = bufmax*2;
216 /* just in case someone's screwing around */
217 if (bufmax > 0xffffffff) {
218 complain(&places.current,
219 "Input line too long");
220 die();
221 }
222 }
223
224 if (ateof) {
225 /* don't read again, in case it's a socket */
226 result = 0;
227 } else {
228 result = read(fd, buf+bufend, bufmax - bufend);
229 }
230
231 if (result == -1) {
232 /* read error */
233 complain(NULL((void*)0), "%s: %s",
234 name, strerror(errno(*__errno())));
235 complain_fail();
236 } else if (result == 0 && bufend == linestart) {
237 /* eof */
238 ateof = true1;
Value stored to 'ateof' is never read
239 break;
240 } else if (result == 0) {
241 /* eof in middle of line */
242 ateof = true1;
243 ptmp = places.current;
244 place_addcolumns(&ptmp, bufend - linestart);
245 if (buf[bufend - 1] == '\n') {
246 complain(&ptmp, "Unclosed comment");
247 complain_fail();
248 } else {
249 complain(&ptmp,
250 "No newline at end of file");
251 }
252 if (mode.werror) {
253 complain_fail();
254 }
255 assert(bufend < bufmax)((bufend < bufmax) ? (void)0 : __assert2("/usr/src/libexec/tradcpp/files.c"
, 255, __func__, "bufend < bufmax"))
;
256 lineend = bufend++;
257 buf[lineend] = '\n';
258 } else {
259 bufend += (size_t)result;
260 lineend = findeol(buf, linestart, bufend);
261 }
262 /* loop in case we still don't have a whole line */
263 continue;
264 }
265
266 /* have a line */
267 assert(buf[lineend] == '\n')((buf[lineend] == '\n') ? (void)0 : __assert2("/usr/src/libexec/tradcpp/files.c"
, 267, __func__, "buf[lineend] == '\\n'"))
;
268 buf[lineend] = '\0';
269 nextlinestart = lineend+1;
270 place_addlines(&places.nextline, 1);
271
272 /* check for CR/NL */
273 if (lineend > 0 && buf[lineend-1] == '\r') {
274 buf[lineend-1] = '\0';
275 lineend--;
276 }
277
278 /* check for continuation line */
279 if (lineend > 0 && buf[lineend-1]=='\\') {
280 lineend--;
281 tmp = nextlinestart - lineend;
282 if (bufend > nextlinestart) {
283 memmove(buf+lineend, buf+nextlinestart,
284 bufend - nextlinestart);
285 }
286 bufend -= tmp;
287 nextlinestart -= tmp;
288 lineend = findeol(buf, linestart, bufend);
289 /* might not have a whole line, so loop */
290 continue;
291 }
292
293 /* line now goes from linestart to lineend */
294 assert(buf[lineend] == '\0')((buf[lineend] == '\0') ? (void)0 : __assert2("/usr/src/libexec/tradcpp/files.c"
, 294, __func__, "buf[lineend] == '\\0'"))
;
295
296 /* count how many commented-out newlines we swallowed */
297 place_addlines(&places.nextline,
298 countnls(buf, linestart, lineend));
299
300 /* process the line (even if it's empty) */
301 directive_gotline(&places, buf+linestart, lineend-linestart);
302
303 linestart = nextlinestart;
304 lineend = findeol(buf, linestart, bufend);
305 places.current = places.nextline;
306 }
307
308 if (toplevel) {
309 directive_goteof(&places.current);
310 }
311 dofree(buf, bufmax);
312}
313
314////////////////////////////////////////////////////////////
315// path search
316
317static
318char *
319mkfilename(struct place *place, const char *dir, const char *file)
320{
321 size_t dlen, flen, rlen;
322 char *ret;
323 bool needslash = false0;
324
325 if (dir == NULL((void*)0)) {
326 dir = place_getparsedir(place);
327 }
328
329 dlen = strlen(dir);
330 flen = strlen(file);
331 if (dlen > 0 && dir[dlen-1] != '/') {
332 needslash = true1;
333 }
334
335 rlen = dlen + (needslash ? 1 : 0) + flen;
336 ret = domalloc(rlen + 1);
337 snprintf(ret, rlen+1, "%s%s%s", dir, needslash ? "/" : "", file);
338 return ret;
339}
340
341static
342int
343file_tryopen(const char *file)
344{
345 int fd;
346
347 /* XXX check for non-regular files */
348
349 fd = open(file, O_RDONLY0x0000);
350 if (fd == -1) {
351 if (errno(*__errno()) != ENOENT2 && errno(*__errno()) != ENOTDIR20) {
352 complain(NULL((void*)0), "%s: %s", file, strerror(errno(*__errno())));
353 }
354 return -1;
355 }
356
357 return fd;
358}
359
360static
361void
362file_search(struct place *place, struct incdirarray *path, const char *name)
363{
364 unsigned i, num;
365 struct incdir *id;
366 const struct placefile *pf;
367 char *file;
368 int fd;
369
370 assert(place != NULL)((place != ((void*)0)) ? (void)0 : __assert2("/usr/src/libexec/tradcpp/files.c"
, 370, __func__, "place != NULL"))
;
371
372 if (name[0] == '/') {
373 fd = file_tryopen(name);
374 if (fd >= 0) {
375 pf = place_addfile(place, name, true1);
376 file_read(pf, fd, name, false0);
377 close(fd);
378 return;
379 }
380 } else {
381 num = incdirarray_num(path);
382 for (i=0; i<num; i++) {
383 id = incdirarray_get(path, i);
384 file = mkfilename(place, id->name, name);
385 fd = file_tryopen(file);
386 if (fd >= 0) {
387 pf = place_addfile(place, file, id->issystem);
388 file_read(pf, fd, file, false0);
389 dostrfree(file);
390 close(fd);
391 return;
392 }
393 dostrfree(file);
394 }
395 }
396 complain(place, "Include file %s not found", name);
397 complain_fail();
398}
399
400void
401file_readquote(struct place *place, const char *name)
402{
403 file_search(place, &quotepath, name);
404}
405
406void
407file_readbracket(struct place *place, const char *name)
408{
409 file_search(place, &bracketpath, name);
410}
411
412void
413file_readabsolute(struct place *place, const char *name)
414{
415 const struct placefile *pf;
416 int fd;
417
418 assert(place != NULL)((place != ((void*)0)) ? (void)0 : __assert2("/usr/src/libexec/tradcpp/files.c"
, 418, __func__, "place != NULL"))
;
419
420 if (name == NULL((void*)0)) {
421 fd = STDIN_FILENO0;
422 pf = place_addfile(place, "<standard-input>", false0);
423 } else {
424 fd = file_tryopen(name);
425 if (fd < 0) {
426 complain(NULL((void*)0), "%s: %s", name, strerror(errno(*__errno())));
427 die();
428 }
429 pf = place_addfile(place, name, false0);
430 }
431
432 file_read(pf, fd, name, true1);
433
434 if (name != NULL((void*)0)) {
435 close(fd);
436 }
437}