Bug Summary

File:src/usr.sbin/mtree/verify.c
Warning:line 87, column 18
Access to field 'parent' results in a dereference of a null pointer (loaded from variable 'level')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name verify.c -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 -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -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/mtree/obj -resource-dir /usr/local/llvm16/lib/clang/16 -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/mtree/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -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/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.sbin/mtree/verify.c
1/* $OpenBSD: verify.c,v 1.21 2016/08/16 16:41:46 krw Exp $ */
2/* $NetBSD: verify.c,v 1.10 1995/03/07 21:26:28 cgd Exp $ */
3
4/*-
5 * Copyright (c) 1990, 1993
6 * The Regents of the University of California. All rights reserved.
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 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/stat.h>
34#include <dirent.h>
35#include <fts.h>
36#include <fnmatch.h>
37#include <unistd.h>
38#include <errno(*__errno()).h>
39#include <stdio.h>
40#include <limits.h>
41#include "mtree.h"
42#include "extern.h"
43
44extern u_int32_t crc_total;
45extern int ftsoptions;
46extern int dflag, eflag, qflag, rflag, sflag, uflag;
47extern char fullpath[PATH_MAX1024];
48
49static NODE *root;
50static char path[PATH_MAX1024];
51
52static void miss(NODE *, char *, size_t);
53static int vwalk(void);
54
55int
56verify(void)
57{
58 int rval;
59
60 root = spec();
1
Value assigned to 'root'
61 rval = vwalk();
2
Calling 'vwalk'
62 miss(root, path, sizeof(path));
63 return (rval);
64}
65
66static int
67vwalk(void)
68{
69 FTS *t;
70 FTSENT *p;
71 NODE *ep, *level;
72 int specdepth, rval;
73 char *argv[2];
74
75 argv[0] = ".";
76 argv[1] = NULL((void *)0);
77 if ((t = fts_open(argv, ftsoptions, dsort)) == NULL((void *)0))
3
Assuming the condition is false
4
Taking false branch
78 error("fts_open: %s", strerror(errno(*__errno())));
79 level = root;
5
The value of 'root' is assigned to 'level'
80 specdepth = rval = 0;
81 while ((p = fts_read(t))) {
6
Loop condition is true. Entering loop body
16
Loop condition is true. Entering loop body
82 switch(p->fts_info) {
7
Control jumps to 'case 1:' at line 83
17
Control jumps to 'case 6:' at line 85
83 case FTS_D1:
84 break;
85 case FTS_DP6:
86 if (specdepth > p->fts_level) {
18
Assuming 'specdepth' is > field 'fts_level'
19
Taking true branch
87 for (level = level->parent; level->prev;
20
Access to field 'parent' results in a dereference of a null pointer (loaded from variable 'level')
88 level = level->prev);
89 --specdepth;
90 }
91 continue;
92 case FTS_DNR4:
93 case FTS_ERR7:
94 case FTS_NS10:
95 (void)fprintf(stderr(&__sF[2]), "mtree: %s: %s\n",
96 RP(p)((p)->fts_path[0] == '.' && (p)->fts_path[1] ==
'/' ? (p)->fts_path + 2 : (p)->fts_path)
, strerror(p->fts_errno));
97 continue;
98 default:
99 if (dflag)
100 continue;
101 }
102
103 if (specdepth != p->fts_level)
8
Execution continues on line 103
9
Assuming 'specdepth' is equal to field 'fts_level'
10
Taking false branch
104 goto extra;
105 for (ep = level; ep; ep = ep->next)
11
Assuming pointer value is null
12
Loop condition is false. Execution continues on line 123
106 if ((ep->flags & F_MAGIC0x000020 &&
107 !fnmatch(ep->name, p->fts_name, FNM_PATHNAME0x02)) ||
108 !strcmp(ep->name, p->fts_name)) {
109 ep->flags |= F_VISIT0x040000;
110 if ((ep->flags & F_NOCHANGE0x100000) == 0 &&
111 compare(ep->name, ep, p))
112 rval = MISMATCHEXIT2;
113 if (ep->flags & F_IGN0x000010)
114 (void)fts_set(t, p, FTS_SKIP4);
115 else if (ep->child && ep->type == F_DIR0x004 &&
116 p->fts_info == FTS_D1) {
117 level = ep->child;
118 ++specdepth;
119 }
120 break;
121 }
122
123 if (ep
12.1
'ep' is null
)
13
Taking false branch
124 continue;
125extra:
126 if (!eflag) {
14
Assuming 'eflag' is not equal to 0
15
Taking false branch
127 (void)printf("extra: %s", RP(p)((p)->fts_path[0] == '.' && (p)->fts_path[1] ==
'/' ? (p)->fts_path + 2 : (p)->fts_path)
);
128 if (rflag) {
129 if ((S_ISDIR(p->fts_statp->st_mode)((p->fts_statp->st_mode & 0170000) == 0040000)
130 ? rmdir : unlink)(p->fts_accpath)) {
131 (void)printf(", not removed: %s",
132 strerror(errno(*__errno())));
133 rval = ERROREXIT1;
134 } else
135 (void)printf(", removed");
136 } else
137 rval = MISMATCHEXIT2;
138 (void)putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
139 }
140 (void)fts_set(t, p, FTS_SKIP4);
141 }
142 (void)fts_close(t);
143 if (sflag)
144 (void)fprintf(stderr(&__sF[2]),
145 "mtree: %s checksum: %u\n", fullpath, crc_total);
146 return (rval);
147}
148
149static void
150miss(NODE *p, char *tail, size_t len)
151{
152 int create;
153 char *tp;
154
155 for (; p; p = p->next) {
156 if ((p->flags & F_OPT0x000200) && !(p->flags & F_VISIT0x040000))
157 continue;
158 if (p->type != F_DIR0x004 && (dflag || p->flags & F_VISIT0x040000))
159 continue;
160 (void)strlcpy(tail, p->name, len);
161 if (!(p->flags & F_VISIT0x040000)) {
162 /* Don't print missing message if file exists as a
163 symbolic link and the -q flag is set. */
164 struct stat statbuf;
165
166 if (qflag && stat(path, &statbuf) == 0)
167 p->flags |= F_VISIT0x040000;
168 else
169 (void)printf("missing: %s", path);
170 }
171 if (p->type != F_DIR0x004) {
172 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
173 continue;
174 }
175
176 create = 0;
177 if (!(p->flags & F_VISIT0x040000) && uflag) {
178 if (!(p->flags & (F_UID0x010000 | F_UNAME0x020000)))
179 (void)printf(" (not created: user not specified)");
180 else if (!(p->flags & (F_GID0x000004 | F_GNAME0x000008)))
181 (void)printf(" (not created: group not specified)");
182 else if (!(p->flags & F_MODE0x000080))
183 (void)printf(" (not created: mode not specified)");
184 else if (mkdir(path, S_IRWXU0000700))
185 (void)printf(" (not created: %s)",
186 strerror(errno(*__errno())));
187 else {
188 create = 1;
189 (void)printf(" (created)");
190 }
191 }
192
193 if (!(p->flags & F_VISIT0x040000))
194 (void)putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
195
196 for (tp = tail; *tp; ++tp);
197 *tp = '/';
198 miss(p->child, tp + 1, len - (tp + 1 - tail));
199 *tp = '\0';
200
201 if (!create)
202 continue;
203 if (chown(path, p->st_uid, p->st_gid)) {
204 (void)printf("%s: user/group/mode not modified: %s\n",
205 path, strerror(errno(*__errno())));
206 continue;
207 }
208 if (chmod(path, p->st_mode))
209 (void)printf("%s: permissions not set: %s\n",
210 path, strerror(errno(*__errno())));
211 }
212}