Bug Summary

File:src/usr.sbin/config/files.c
Warning:line 146, column 6
2nd function call argument is an uninitialized 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 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/usr.sbin/config/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/config -I . -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/config/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/usr.sbin/config/files.c
1/* $OpenBSD: files.c,v 1.20 2015/01/16 06:40:16 deraadt Exp $ */
2/* $NetBSD: files.c,v 1.6 1996/03/17 13:18:17 cgd Exp $ */
3
4/*
5 * Copyright (c) 1992, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This software was developed by the Computer Systems Engineering group
9 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
10 * contributed to Berkeley.
11 *
12 * All advertising materials mentioning features or use of this software
13 * must display the following acknowledgement:
14 * This product includes software developed by the University of
15 * California, Lawrence Berkeley Laboratories.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 * 3. Neither the name of the University nor the names of its contributors
26 * may be used to endorse or promote products derived from this software
27 * without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * SUCH DAMAGE.
40 *
41 * from: @(#)files.c 8.1 (Berkeley) 6/6/93
42 */
43
44#include <errno(*__errno()).h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48
49#include "config.h"
50
51extern const char *yyfile;
52
53/*
54 * We check that each full path name is unique. File base names
55 * should generally also be unique, e.g., having both a net/xx.c and
56 * a kern/xx.c (or, worse, a net/xx.c and a new/xx.c++) is probably
57 * wrong, but is permitted under some conditions.
58 */
59static struct hashtab *basetab; /* file base names */
60static struct hashtab *pathtab; /* full path names */
61
62static struct files **nextfile;
63static struct files **unchecked;
64
65static struct objects **nextobject;
66
67static int checkaux(const char *, void *);
68static int fixcount(const char *, void *);
69static int fixfsel(const char *, void *);
70static int fixsel(const char *, void *);
71static int expr_eval(struct nvlist *,
72 int (*)(const char *, void *), void *);
73static void expr_free(struct nvlist *);
74
75#ifdef DEBUG
76static void pr0();
77#endif
78
79void
80initfiles(void)
81{
82
83 basetab = ht_new();
84 pathtab = ht_new();
85 nextfile = &allfiles;
86 unchecked = &allfiles;
87 nextobject = &allobjects;
88}
89
90void
91addfile(struct nvlist *nvpath, struct nvlist *optx, int flags, const char *rule)
92{
93 struct files *fi;
94 const char *dotp, *dotp1, *tail, *path, *tail1 = NULL((void *)0);
1
'path' declared without an initial value
95 struct nvlist *nv;
96 size_t baselen;
97 int needc, needf;
98 char base[200];
99
100 /* check various errors */
101 needc = flags & FI_NEEDSCOUNT0x02;
102 needf = flags & FI_NEEDSFLAG0x04;
103 if (needc && needf) {
2
Assuming 'needc' is 0
104 error("cannot mix needs-count and needs-flag");
105 goto bad;
106 }
107 if (optx == NULL((void *)0) && (needc || needf)) {
3
Assuming 'optx' is not equal to NULL
108 error("nothing to %s", needc ? "count" : "flag");
109 goto bad;
110 }
111
112 for (nv = nvpath; nv; nv = nv->nv_next) {
4
Loop condition is false. Execution continues on line 145
113 path = nv->nv_name;
114
115 /* find last part of pathname, and same without trailing suffix */
116 tail = strrchr(path, '/');
117 if (tail == NULL((void *)0))
118 tail = path;
119 else
120 tail++;
121 dotp = strrchr(tail, '.');
122 if (dotp == NULL((void *)0) || dotp[1] == 0 ||
123 (baselen = dotp - tail) >= sizeof(base)) {
124 error("invalid pathname `%s'", path);
125 goto bad;
126 }
127
128 /*
129 * Ensure all tailnames are identical, because .o
130 * filenames must be identical too.
131 */
132 if (tail1 &&
133 (dotp - tail != dotp1 - tail1 ||
134 strncmp(tail1, tail, dotp - tail)))
135 error("different production from %s %s",
136 nvpath->nv_name, tail);
137 tail1 = tail;
138 dotp1 = dotp;
139 }
140
141 /*
142 * Commit this file to memory. We will decide later whether it
143 * will be used after all.
144 */
145 fi = emalloc(sizeof *fi);
146 if (ht_insert(pathtab, path, fi)ht_insrep(pathtab, path, fi, 0)) {
5
2nd function call argument is an uninitialized value
147 free(fi);
148 if ((fi = ht_lookup(pathtab, path)) == NULL((void *)0))
149 panic("addfile: ht_lookup(%s)", path);
150 error("duplicate file %s", path);
151 xerror(fi->fi_srcfile, fi->fi_srcline,
152 "here is the original definition");
153 }
154 memcpy(base, tail, baselen);
155 base[baselen] = 0;
156 fi->fi_next = NULL((void *)0);
157 fi->fi_srcfile = yyfile;
158 fi->fi_srcline = currentline();
159 fi->fi_flags = flags;
160 fi->fi_nvpath = nvpath;
161 fi->fi_base = intern(base);
162 fi->fi_optx = optx;
163 fi->fi_optf = NULL((void *)0);
164 fi->fi_mkrule = rule;
165 *nextfile = fi;
166 nextfile = &fi->fi_next;
167 return;
168bad:
169 expr_free(optx);
170}
171
172void
173addobject(const char *path, struct nvlist *optx, int flags)
174{
175 struct objects *oi;
176
177 /*
178 * Commit this object to memory. We will decide later whether it
179 * will be used after all.
180 */
181 oi = emalloc(sizeof *oi);
182 if (ht_insert(pathtab, path, oi)ht_insrep(pathtab, path, oi, 0)) {
183 free(oi);
184 if ((oi = ht_lookup(pathtab, path)) == NULL((void *)0))
185 panic("addfile: ht_lookup(%s)", path);
186 error("duplicate file %s", path);
187 xerror(oi->oi_srcfile, oi->oi_srcline,
188 "here is the original definition");
189 }
190 oi->oi_next = NULL((void *)0);
191 oi->oi_srcfile = yyfile;
192 oi->oi_srcline = currentline();
193 oi->oi_flags = flags;
194 oi->oi_path = path;
195 oi->oi_optx = optx;
196 oi->oi_optf = NULL((void *)0);
197 *nextobject = oi;
198 nextobject = &oi->oi_next;
199}
200
201/*
202 * We have finished reading some "files" file, either ../../conf/files
203 * or ./files.$machine. Make sure that everything that is flagged as
204 * needing a count is reasonable. (This prevents ../../conf/files from
205 * depending on some machine-specific device.)
206 */
207void
208checkfiles(void)
209{
210 struct files *fi, *last;
211
212 last = NULL((void *)0);
213 for (fi = *unchecked; fi != NULL((void *)0); last = fi, fi = fi->fi_next)
214 if ((fi->fi_flags & FI_NEEDSCOUNT0x02) != 0)
215 (void)expr_eval(fi->fi_optx, checkaux, fi);
216 if (last != NULL((void *)0))
217 unchecked = &last->fi_next;
218}
219
220/*
221 * Auxiliary function for checkfiles, called from expr_eval.
222 * We are not actually interested in the expression's value.
223 */
224static int
225checkaux(const char *name, void *context)
226{
227 struct files *fi = context;
228
229 if (ht_lookup(devbasetab, name) == NULL((void *)0)) {
230 xerror(fi->fi_srcfile, fi->fi_srcline,
231 "`%s' is not a countable device",
232 name);
233 /* keep fixfiles() from complaining again */
234 fi->fi_flags |= FI_HIDDEN0x08;
235 }
236 return (0);
237}
238
239/*
240 * We have finished reading everything. Tack the files down: calculate
241 * selection and counts as needed. Check that the object files built
242 * from the selected sources do not collide.
243 */
244int
245fixfiles(void)
246{
247 struct files *fi, *ofi;
248 struct nvlist *flathead, **flatp;
249 int err, sel;
250
251 err = 0;
252 for (fi = allfiles; fi != NULL((void *)0); fi = fi->fi_next) {
253 /* Skip files that generated counted-device complaints. */
254 if (fi->fi_flags & FI_HIDDEN0x08)
255 continue;
256
257 /* Optional: see if it is to be included. */
258 if (fi->fi_optx != NULL((void *)0)) {
259 flathead = NULL((void *)0);
260 flatp = &flathead;
261 sel = expr_eval(fi->fi_optx,
262 fi->fi_flags & FI_NEEDSCOUNT0x02 ? fixcount :
263 fi->fi_flags & FI_NEEDSFLAG0x04 ? fixfsel :
264 fixsel,
265 &flatp);
266 fi->fi_optf = flathead;
267 if (!sel)
268 continue;
269 }
270
271 /* We like this file. Make sure it generates a unique .o. */
272 if (ht_insert(basetab, fi->fi_base, fi)ht_insrep(basetab, fi->fi_base, fi, 0)) {
273 if ((ofi = ht_lookup(basetab, fi->fi_base)) == NULL((void *)0))
274 panic("fixfiles ht_lookup(%s)", fi->fi_base);
275 /*
276 * If the new file comes from a different source,
277 * allow the new one to override the old one.
278 */
279 if (fi->fi_nvpath != ofi->fi_nvpath) {
280 if (ht_replace(basetab, fi->fi_base, fi)ht_insrep(basetab, fi->fi_base, fi, 1) != 1)
281 panic("fixfiles ht_replace(%s)",
282 fi->fi_base);
283 ofi->fi_flags &= ~FI_SEL0x01;
284 ofi->fi_flags |= FI_HIDDEN0x08;
285 } else {
286 xerror(fi->fi_srcfile, fi->fi_srcline,
287 "object file collision on %s.o, from %s",
288 fi->fi_base, fi->fi_nvpath->nv_name);
289 xerror(ofi->fi_srcfile, ofi->fi_srcline,
290 "here is the previous file: %s",
291 ofi->fi_nvpath->nv_name);
292 err = 1;
293 }
294 }
295 fi->fi_flags |= FI_SEL0x01;
296 }
297 return (err);
298}
299
300/*
301 * We have finished reading everything. Tack the objects down: calculate
302 * selection.
303 */
304int
305fixobjects(void)
306{
307 struct objects *oi;
308 struct nvlist *flathead, **flatp;
309 int err, sel;
310
311 err = 0;
312 for (oi = allobjects; oi != NULL((void *)0); oi = oi->oi_next) {
313 /* Optional: see if it is to be included. */
314 if (oi->oi_optx != NULL((void *)0)) {
315 flathead = NULL((void *)0);
316 flatp = &flathead;
317 sel = expr_eval(oi->oi_optx,
318 oi->oi_flags & OI_NEEDSFLAG0x02 ? fixfsel :
319 fixsel,
320 &flatp);
321 oi->oi_optf = flathead;
322 if (!sel)
323 continue;
324 }
325
326 oi->oi_flags |= OI_SEL0x01;
327 }
328 return (err);
329}
330
331/*
332 * Called when evaluating a needs-count expression. Make sure the
333 * atom is a countable device. The expression succeeds iff there
334 * is at least one of them (note that while `xx*' will not always
335 * set xx's d_umax > 0, you cannot mix '*' and needs-count). The
336 * mkheaders() routine wants a flattened, in-order list of the
337 * atoms for `#define name value' lines, so we build that as we
338 * are called to eval each atom.
339 */
340static int
341fixcount(const char *name, void *context)
342{
343 struct nvlist ***p = context;
344 struct devbase *dev;
345 struct nvlist *nv;
346
347 dev = ht_lookup(devbasetab, name);
348 if (dev == NULL((void *)0)) /* cannot occur here; we checked earlier */
349 panic("fixcount(%s)", name);
350 nv = newnv(name, NULL((void *)0), NULL((void *)0), dev->d_umax, NULL((void *)0));
351 **p = nv;
352 *p = &nv->nv_next;
353 (void)ht_insert(needcnttab, name, nv)ht_insrep(needcnttab, name, nv, 0);
354 return (dev->d_umax != 0);
355}
356
357/*
358 * Called from fixfiles when eval'ing a selection expression for a
359 * file that will generate a .h with flags. We will need the flat list.
360 */
361static int
362fixfsel(const char *name, void *context)
363{
364 struct nvlist ***p = context;
365 struct nvlist *nv;
366 int sel;
367
368 sel = ht_lookup(selecttab, name) != NULL((void *)0);
369 nv = newnv(name, NULL((void *)0), NULL((void *)0), sel, NULL((void *)0));
370 **p = nv;
371 *p = &nv->nv_next;
372 return (sel);
373}
374
375/*
376 * As for fixfsel above, but we do not need the flat list.
377 */
378static int
379fixsel(const char *name, void *context)
380{
381
382 return (ht_lookup(selecttab, name) != NULL((void *)0));
383}
384
385/*
386 * Eval an expression tree. Calls the given function on each node,
387 * passing it the given context & the name; return value is &/|/! of
388 * results of evaluating atoms.
389 *
390 * No short circuiting ever occurs. fn must return 0 or 1 (otherwise
391 * our mixing of C's bitwise & boolean here may give surprises).
392 */
393static int
394expr_eval(struct nvlist *expr, int (*fn)(const char *, void *), void *context)
395{
396 int lhs, rhs;
397
398 switch (expr->nv_int) {
399
400 case FX_ATOM0:
401 return ((*fn)(expr->nv_name, context));
402
403 case FX_NOT1:
404 return (!expr_eval(expr->nv_next, fn, context));
405
406 case FX_AND2:
407 lhs = expr_eval(expr->nv_ptrnv_un.un_ptr, fn, context);
408 rhs = expr_eval(expr->nv_next, fn, context);
409 return (lhs & rhs);
410
411 case FX_OR3:
412 lhs = expr_eval(expr->nv_ptrnv_un.un_ptr, fn, context);
413 rhs = expr_eval(expr->nv_next, fn, context);
414 return (lhs | rhs);
415 }
416 panic("expr_eval %d", expr->nv_int);
417 return (0);
418}
419
420/*
421 * Free an expression tree.
422 */
423static void
424expr_free(struct nvlist *expr)
425{
426 struct nvlist *rhs;
427
428 /* This loop traverses down the RHS of each subexpression. */
429 for (; expr != NULL((void *)0); expr = rhs) {
430 switch (expr->nv_int) {
431
432 /* Atoms and !-exprs have no left hand side. */
433 case FX_ATOM0:
434 case FX_NOT1:
435 break;
436
437 /* For AND and OR nodes, free the LHS. */
438 case FX_AND2:
439 case FX_OR3:
440 expr_free(expr->nv_ptrnv_un.un_ptr);
441 break;
442
443 default:
444 panic("expr_free %d", expr->nv_int);
445 }
446 rhs = expr->nv_next;
447 nvfree(expr);
448 }
449}
450
451#ifdef DEBUG
452/*
453 * Print expression tree.
454 */
455void
456prexpr(struct nvlist *expr)
457{
458 printf("expr =");
459 pr0(expr);
460 printf("\n");
461 (void)fflush(stdout(&__sF[1]));
462}
463
464static void
465pr0(struct nvlist *e)
466{
467
468 switch (e->nv_int) {
469 case FX_ATOM0:
470 printf(" %s", e->nv_name);
471 return;
472 case FX_NOT1:
473 printf(" (!");
474 break;
475 case FX_AND2:
476 printf(" (&");
477 break;
478 case FX_OR3:
479 printf(" (|");
480 break;
481 default:
482 printf(" (?%d?", e->nv_int);
483 break;
484 }
485 if (e->nv_ptrnv_un.un_ptr)
486 pr0(e->nv_ptrnv_un.un_ptr);
487 pr0(e->nv_next);
488 printf(")");
489}
490#endif