clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name spec.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/spec.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | #include <sys/types.h> |
34 | #include <sys/stat.h> |
35 | #include <pwd.h> |
36 | #include <grp.h> |
37 | #include <errno.h> |
38 | #include <unistd.h> |
39 | #include <stdio.h> |
40 | #include <ctype.h> |
41 | #include <vis.h> |
42 | #include "mtree.h" |
43 | #include "extern.h" |
44 | |
45 | int lineno; |
46 | |
47 | static void set(char *, NODE *); |
48 | static void unset(char *, NODE *); |
49 | |
50 | NODE * |
51 | spec(void) |
52 | { |
53 | NODE *centry, *last; |
54 | char *p; |
55 | NODE ginfo, *root; |
56 | int c_cur, c_next; |
57 | char *buf, *tbuf = NULL; |
58 | size_t len; |
59 | |
60 | last = root = NULL; |
61 | bzero(&ginfo, sizeof(ginfo)); |
62 | centry = &ginfo; |
63 | c_cur = c_next = 0; |
64 | for (lineno = 1; (buf = fgetln(stdin, &len)); |
| 1 | Loop condition is true. Entering loop body | |
|
65 | ++lineno, c_cur = c_next, c_next = 0) { |
66 | |
67 | if (buf[len - 1] == '\n') { |
| 2 | | Assuming the condition is false | |
|
| |
68 | buf[--len] = '\0'; |
69 | } else { |
70 | |
71 | tbuf = malloc(len + 1); |
72 | memcpy(tbuf, buf, len); |
73 | tbuf[len] = '\0'; |
74 | buf = tbuf; |
75 | } |
76 | |
77 | |
78 | for (p = buf; isspace((unsigned char)*p); p++) |
| 4 | | Assuming the character is not a whitespace character | |
|
79 | ; |
80 | |
81 | |
82 | if (*p == '\0' || *p == '#') |
| 5 | | Assuming the condition is false | |
|
| 6 | | Assuming the condition is false | |
|
| |
83 | continue; |
84 | |
85 | |
86 | if (buf[len - 1] == '\\') { |
| 8 | | Assuming the condition is false | |
|
| |
87 | c_next = 1; |
88 | if (--len == 0) |
89 | continue; |
90 | buf[len] = '\0'; |
91 | } |
92 | |
93 | #ifdef DEBUG |
94 | (void)fprintf(stderr, "line %d: {%s}\n", lineno, p); |
95 | #endif |
96 | if (c_cur) { |
| |
97 | set(p, centry); |
98 | continue; |
99 | } |
100 | |
101 | |
102 | if ((p = strtok(p, "\n\t ")) == NULL) |
| 11 | | Assuming the condition is false | |
|
| |
103 | error("missing field"); |
104 | |
105 | if (p[0] == '/') |
| 13 | | Assuming the condition is true | |
|
| |
106 | switch(p[1]) { |
| 15 | | Control jumps to 'case 115:' at line 107 | |
|
107 | case 's': |
108 | if (strcmp(p + 1, "set")) |
| 16 | | Assuming the condition is false | |
|
| |
109 | break; |
110 | set(NULL, &ginfo); |
| |
111 | continue; |
112 | case 'u': |
113 | if (strcmp(p + 1, "unset")) |
114 | break; |
115 | unset(NULL, &ginfo); |
116 | continue; |
117 | } |
118 | |
119 | if (strchr(p, '/')) |
120 | error("slash character in file name"); |
121 | |
122 | if (!strcmp(p, "..")) { |
123 | |
124 | if (!root) |
125 | goto noparent; |
126 | if (last->type != F_DIR || last->flags & F_DONE) { |
127 | if (last == root) |
128 | goto noparent; |
129 | last = last->parent; |
130 | } |
131 | last->flags |= F_DONE; |
132 | continue; |
133 | |
134 | noparent: error("no parent node"); |
135 | } |
136 | |
137 | len = strlen(p) + 1; |
138 | if ((centry = calloc(1, sizeof(NODE) + len - 1)) == NULL) |
139 | error("%s", strerror(errno)); |
140 | *centry = ginfo; |
141 | #define MAGIC "?*[" |
142 | if (strpbrk(p, MAGIC)) |
143 | centry->flags |= F_MAGIC; |
144 | if (strunvis(centry->name, p) == -1) { |
145 | fprintf(stderr, |
146 | "mtree: filename (%s) encoded incorrectly\n", p); |
147 | strlcpy(centry->name, p, len); |
148 | } |
149 | set(NULL, centry); |
150 | |
151 | if (!root) { |
152 | last = root = centry; |
153 | root->parent = root; |
154 | } else if (last->type == F_DIR && !(last->flags & F_DONE)) { |
155 | centry->parent = last; |
156 | last = last->child = centry; |
157 | } else { |
158 | centry->parent = last->parent; |
159 | centry->prev = last; |
160 | last = last->next = centry; |
161 | } |
162 | } |
163 | free(tbuf); |
164 | return (root); |
165 | } |
166 | |
167 | static void |
168 | set(char *t, NODE *ip) |
169 | { |
170 | int type; |
171 | char *kw, *val = NULL; |
172 | void *m; |
173 | int value; |
174 | u_int32_t fset, fclr; |
175 | char *ep; |
176 | size_t len; |
177 | |
178 | for (; (kw = strtok(t, "= \t\n")); t = NULL) { |
| 19 | | Loop condition is true. Entering loop body | |
|
| 29 | | Execution continues on line 178 | |
|
| 30 | | Loop condition is true. Entering loop body | |
|
179 | ip->flags |= type = parsekey(kw, &value); |
180 | if (value && (val = strtok(NULL, " \t\n")) == NULL) |
| 20 | | Assuming 'value' is not equal to 0 | |
|
| 21 | | Assuming the condition is false | |
|
| |
| |
181 | error("missing value"); |
182 | switch(type) { |
| 23 | | Control jumps to 'case 8192:' at line 245 | |
|
| 32 | | Control jumps to 'case 8192:' at line 245 | |
|
183 | case F_CKSUM: |
184 | ip->cksum = strtoul(val, &ep, 10); |
185 | if (*ep) |
186 | error("invalid checksum %s", val); |
187 | break; |
188 | case F_MD5: |
189 | ip->md5digest = strdup(val); |
190 | if (!ip->md5digest) |
191 | error("%s", strerror(errno)); |
192 | break; |
193 | case F_FLAGS: |
194 | if (!strcmp(val, "none")) { |
195 | ip->file_flags = 0; |
196 | break; |
197 | } |
198 | if (strtofflags(&val, &fset, &fclr)) |
199 | error("%s", strerror(errno)); |
200 | ip->file_flags = fset; |
201 | break; |
202 | case F_GID: |
203 | ip->st_gid = strtoul(val, &ep, 10); |
204 | if (*ep) |
205 | error("invalid gid %s", val); |
206 | break; |
207 | case F_GNAME: |
208 | if (gid_from_group(val, &ip->st_gid) == -1) |
209 | error("unknown group %s", val); |
210 | break; |
211 | case F_IGN: |
212 | |
213 | break; |
214 | case F_MODE: |
215 | if ((m = setmode(val)) == NULL) |
216 | error("invalid file mode %s", val); |
217 | ip->st_mode = getmode(m, 0); |
218 | free(m); |
219 | break; |
220 | case F_NLINK: |
221 | ip->st_nlink = strtoul(val, &ep, 10); |
222 | if (*ep) |
223 | error("invalid link count %s", val); |
224 | break; |
225 | case F_RMD160: |
226 | ip->rmd160digest = strdup(val); |
227 | if (!ip->rmd160digest) |
228 | error("%s", strerror(errno)); |
229 | break; |
230 | case F_SHA1: |
231 | ip->sha1digest = strdup(val); |
232 | if (!ip->sha1digest) |
233 | error("%s", strerror(errno)); |
234 | break; |
235 | case F_SHA256: |
236 | ip->sha256digest = strdup(val); |
237 | if (!ip->sha256digest) |
238 | error("%s", strerror(errno)); |
239 | break; |
240 | case F_SIZE: |
241 | ip->st_size = strtoll(val, &ep, 10); |
242 | if (*ep) |
243 | error("invalid size %s", val); |
244 | break; |
245 | case F_SLINK: |
246 | len = strlen(val) + 1; |
247 | if ((ip->slink = malloc(len)) == NULL) |
| |
| 25 | | Assuming the condition is false | |
|
| |
| 33 | | Assuming the condition is false | |
|
| |
248 | error("%s", strerror(errno)); |
249 | if (strunvis(ip->slink, val) == -1) { |
| 27 | | Assuming the condition is false | |
|
| |
| |
250 | fprintf(stderr, |
251 | "mtree: filename (%s) encoded incorrectly\n", val); |
252 | strlcpy(ip->slink, val, len); |
253 | } |
254 | break; |
255 | case F_TIME: |
256 | ip->st_mtim.tv_sec = strtoull(val, &ep, 10); |
257 | if (*ep != '.') |
258 | error("invalid time %s", val); |
259 | val = ep + 1; |
260 | ip->st_mtim.tv_nsec = strtoul(val, &ep, 10); |
261 | if (*ep) |
262 | error("invalid time %s", val); |
263 | break; |
264 | case F_TYPE: |
265 | switch(*val) { |
266 | case 'b': |
267 | if (!strcmp(val, "block")) |
268 | ip->type = F_BLOCK; |
269 | break; |
270 | case 'c': |
271 | if (!strcmp(val, "char")) |
272 | ip->type = F_CHAR; |
273 | break; |
274 | case 'd': |
275 | if (!strcmp(val, "dir")) |
276 | ip->type = F_DIR; |
277 | break; |
278 | case 'f': |
279 | if (!strcmp(val, "file")) |
280 | ip->type = F_FILE; |
281 | if (!strcmp(val, "fifo")) |
282 | ip->type = F_FIFO; |
283 | break; |
284 | case 'l': |
285 | if (!strcmp(val, "link")) |
286 | ip->type = F_LINK; |
287 | break; |
288 | case 's': |
289 | if (!strcmp(val, "socket")) |
290 | ip->type = F_SOCK; |
291 | break; |
292 | default: |
293 | error("unknown file type %s", val); |
294 | } |
295 | break; |
296 | case F_UID: |
297 | ip->st_uid = strtoul(val, &ep, 10); |
298 | if (*ep) |
299 | error("invalid uid %s", val); |
300 | break; |
301 | case F_UNAME: |
302 | if (uid_from_user(val, &ip->st_uid) == -1) |
303 | error("unknown user %s", val); |
304 | break; |
305 | } |
306 | } |
307 | } |
308 | |
309 | static void |
310 | unset(char *t, NODE *ip) |
311 | { |
312 | char *p; |
313 | |
314 | while ((p = strtok(t, "\n\t "))) |
315 | ip->flags &= ~parsekey(p, NULL); |
316 | } |