Bug Summary

File:src/bin/chmod/chmod.c
Warning:line 265, column 8
1st 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 chmod.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/bin/chmod/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/bin/chmod/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/bin/chmod/chmod.c
1/* $OpenBSD: chmod.c,v 1.43 2018/09/16 02:44:06 millert Exp $ */
2/* $NetBSD: chmod.c,v 1.12 1995/03/21 09:02:09 cgd Exp $ */
3
4/*
5 * Copyright (c) 1989, 1993, 1994
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/types.h>
34#include <sys/stat.h>
35
36#include <err.h>
37#include <errno(*__errno()).h>
38#include <fcntl.h>
39#include <fts.h>
40#include <grp.h>
41#include <limits.h>
42#include <pwd.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <string.h>
46#include <unistd.h>
47
48int ischflags, ischown, ischgrp, ischmod;
49extern char *__progname;
50
51gid_t a_gid(const char *);
52uid_t a_uid(const char *, int);
53static void __dead__attribute__((__noreturn__)) usage(void);
54
55int
56main(int argc, char *argv[])
57{
58 FTS *ftsp;
59 FTSENT *p;
60 void *set;
1
'set' declared without an initial value
61 unsigned long val;
62 int oct;
63 mode_t omode;
64 int Hflag, Lflag, Rflag, ch, fflag, fts_options, hflag, rval, atflags;
65 uid_t uid;
66 gid_t gid;
67 u_int32_t fclear, fset;
68 char *ep, *mode, *cp, *flags;
69
70 if (strlen(__progname) > 2) {
2
Assuming the condition is false
3
Taking false branch
71 ischown = __progname[2] == 'o';
72 ischgrp = __progname[2] == 'g';
73 ischmod = __progname[2] == 'm';
74 ischflags = __progname[2] == 'f';
75 }
76
77 uid = (uid_t)-1;
78 gid = (gid_t)-1;
79 Hflag = Lflag = Rflag = fflag = hflag = 0;
80 while ((ch = getopt(argc, argv, "HLPRXfghorstuwx")) != -1)
4
Assuming the condition is true
5
Loop condition is true. Entering loop body
8
Assuming the condition is false
9
Loop condition is false. Execution continues on line 125
81 switch (ch) {
6
Control jumps to 'case 104:' at line 99
82 case 'H':
83 Hflag = 1;
84 Lflag = 0;
85 break;
86 case 'L':
87 Lflag = 1;
88 Hflag = 0;
89 break;
90 case 'P':
91 Hflag = Lflag = 0;
92 break;
93 case 'R':
94 Rflag = 1;
95 break;
96 case 'f': /* no longer documented. */
97 fflag = 1;
98 break;
99 case 'h':
100 hflag = 1;
101 break;
7
Execution continues on line 80
102 /*
103 * If this is a symbolic mode argument rather than
104 * an option, we are done with option processing.
105 */
106 case 'g': case 'o': case 'r': case 's':
107 case 't': case 'u': case 'w': case 'X': case 'x':
108 if (!ischmod)
109 usage();
110 /*
111 * If getopt() moved past the argument, back up.
112 * If the argument contains option letters before
113 * mode letters, setmode() will catch them.
114 */
115 if (optind > 1) {
116 cp = argv[optind - 1];
117 if (cp[strlen(cp) - 1] == ch)
118 --optind;
119 }
120 goto done;
121 default:
122 usage();
123 }
124done:
125 argv += optind;
126 argc -= optind;
127
128 if (argc < 2)
10
Assuming 'argc' is >= 2
11
Taking false branch
129 usage();
130
131 /*
132 * We alter the symlink itself if doing -h or -RP, or
133 * if doing -RH and the symlink wasn't a command line arg.
134 */
135 atflags = AT_SYMLINK_NOFOLLOW0x02;
136
137 fts_options = FTS_PHYSICAL0x0010;
138 if (Rflag
11.1
'Rflag' is 0
) {
12
Taking false branch
139 if (hflag)
140 errx(1,
141 "the -R and -h options may not be specified together.");
142 if (Hflag)
143 fts_options |= FTS_COMFOLLOW0x0001;
144 if (Lflag) {
145 fts_options &= ~FTS_PHYSICAL0x0010;
146 fts_options |= FTS_LOGICAL0x0002;
147 atflags = 0;
148 }
149 } else if (!hflag
12.1
'hflag' is 1
) {
13
Taking false branch
150 fts_options |= FTS_COMFOLLOW0x0001;
151 atflags = 0;
152 }
153
154 if (ischflags) {
14
Assuming 'ischflags' is not equal to 0
15
Taking true branch
155 if (pledge("stdio rpath fattr", NULL((void *)0)) == -1)
16
Assuming the condition is false
17
Taking false branch
156 err(1, "pledge");
157
158 flags = *argv;
159 if (*flags >= '0' && *flags <= '7') {
18
Assuming the condition is false
160 errno(*__errno()) = 0;
161 val = strtoul(flags, &ep, 8);
162 if (val > UINT_MAX(2147483647 *2U +1U))
163 errno(*__errno()) = ERANGE34;
164 if (errno(*__errno()))
165 err(1, "invalid flags: %s", flags);
166 if (*ep)
167 errx(1, "invalid flags: %s", flags);
168 fset = val;
169 oct = 1;
170 } else {
171 if (strtofflags(&flags, &fset, &fclear))
19
Assuming the condition is false
20
Taking false branch
172 errx(1, "invalid flag: %s", flags);
173 fclear = ~fclear;
174 oct = 0;
175 }
176 } else if (ischmod) {
177 mode = *argv;
178 if (*mode >= '0' && *mode <= '7') {
179 errno(*__errno()) = 0;
180 val = strtoul(mode, &ep, 8);
181 if (val > INT_MAX2147483647)
182 errno(*__errno()) = ERANGE34;
183 if (errno(*__errno()))
184 err(1, "invalid file mode: %s", mode);
185 if (*ep)
186 errx(1, "invalid file mode: %s", mode);
187 omode = val;
188 oct = 1;
189 } else {
190 if ((set = setmode(mode)) == NULL((void *)0))
191 errx(1, "invalid file mode: %s", mode);
192 oct = 0;
193 }
194 } else if (ischown) {
195 /* Both UID and GID are given. */
196 if ((cp = strchr(*argv, ':')) != NULL((void *)0)) {
197 *cp++ = '\0';
198 gid = a_gid(cp);
199 }
200 /*
201 * UID and GID are separated by a dot and UID exists.
202 * required for backwards compatibility pre-dating POSIX.2
203 * likely to stay here forever
204 */
205 else if ((cp = strchr(*argv, '.')) != NULL((void *)0) &&
206 (uid = a_uid(*argv, 1)) == (uid_t)-1) {
207 *cp++ = '\0';
208 gid = a_gid(cp);
209 }
210 if (uid == (uid_t)-1)
211 uid = a_uid(*argv, 0);
212 } else
213 gid = a_gid(*argv);
214
215 if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL((void *)0))
21
Assuming the condition is false
22
Taking false branch
216 err(1, NULL((void *)0));
217 for (rval = 0; (p = fts_read(ftsp)) != NULL((void *)0);) {
23
Assuming the condition is true
24
Loop condition is true. Entering loop body
218 switch (p->fts_info) {
25
Control jumps to the 'default' case at line 250
219 case FTS_D1:
220 if (!Rflag)
221 fts_set(ftsp, p, FTS_SKIP4);
222 if (ischmod)
223 break;
224 else
225 continue;
226 case FTS_DNR4: /* Warn, chmod, continue. */
227 warnc(p->fts_errno, "%s", p->fts_path);
228 rval = 1;
229 break;
230 case FTS_DP6: /* Already changed at FTS_D. */
231 if (ischmod)
232 continue;
233 else
234 break;
235 case FTS_ERR7: /* Warn, continue. */
236 case FTS_NS10:
237 warnc(p->fts_errno, "%s", p->fts_path);
238 rval = 1;
239 continue;
240 case FTS_SL12: /* Ignore. */
241 case FTS_SLNONE13:
242 /*
243 * The only symlinks that end up here are ones that
244 * don't point to anything or that loop and ones
245 * that we found doing a physical walk.
246 */
247 if (!hflag && (fts_options & FTS_LOGICAL0x0002))
248 continue;
249 break;
250 default:
251 break;
26
Execution continues on line 258
252 }
253
254 /*
255 * For -RH, the decision of how to handle symlinks depends
256 * on the level: follow it iff it's a command line arg.
257 */
258 if (fts_options & FTS_COMFOLLOW0x0001) {
27
Taking false branch
259 atflags = p->fts_level == FTS_ROOTLEVEL0 ? 0 :
260 AT_SYMLINK_NOFOLLOW0x02;
261 }
262
263 if (ischmod) {
28
Assuming 'ischmod' is not equal to 0
29
Taking true branch
264 if (!fchmodat(AT_FDCWD-100, p->fts_accpath, oct
29.1
'oct' is 0
? omode :
30
'?' condition is false
265 getmode(set, p->fts_statp->st_mode), atflags)
31
1st function call argument is an uninitialized value
266 || fflag)
267 continue;
268 } else if (!ischflags) {
269 if (!fchownat(AT_FDCWD-100, p->fts_accpath, uid, gid,
270 atflags) || fflag)
271 continue;
272 } else {
273 if (!chflagsat(AT_FDCWD-100, p->fts_accpath, oct ? fset :
274 (p->fts_statp->st_flags | fset) & fclear, atflags))
275 continue;
276 }
277
278 /* error case */
279 warn("%s", p->fts_path);
280 rval = 1;
281 }
282 if (errno(*__errno()))
283 err(1, "fts_read");
284 fts_close(ftsp);
285 return (rval);
286}
287
288/*
289 * Given a UID or user name in a string, return the UID. If an empty string
290 * was given, returns -1. If silent is 0, exits on invalid user names/UIDs;
291 * otherwise, returns -1.
292 */
293uid_t
294a_uid(const char *s, int silent)
295{
296 const char *errstr;
297 uid_t uid;
298
299 if (*s == '\0') /* Argument was "[:.]gid". */
300 return ((uid_t)-1);
301
302 /* User name was given. */
303 if (uid_from_user(s, &uid) != -1)
304 return (uid);
305
306 /* UID was given. */
307 uid = (uid_t)strtonum(s, 0, UID_MAX(2147483647 *2U +1U), &errstr);
308 if (errstr) {
309 if (silent)
310 return ((uid_t)-1);
311 else
312 errx(1, "user is %s: %s", errstr, s);
313 }
314
315 return (uid);
316}
317
318/*
319 * Given a GID or group name in a string, return the GID. If an empty string
320 * was given, returns -1. Exits on invalid user names/UIDs.
321 */
322gid_t
323a_gid(const char *s)
324{
325 const char *errstr;
326 gid_t gid;
327
328 if (*s == '\0') /* Argument was "uid[:.]". */
329 return ((gid_t)-1);
330
331 /* Group name was given. */
332 if (gid_from_group(s, &gid) != -1)
333 return (gid);
334
335 /* GID was given. */
336 gid = (gid_t)strtonum(s, 0, GID_MAX(2147483647 *2U +1U), &errstr);
337 if (errstr)
338 errx(1, "group is %s: %s", errstr, s);
339
340 return (gid);
341}
342
343static void __dead__attribute__((__noreturn__))
344usage(void)
345{
346 fprintf(stderr(&__sF[2]),
347 "usage: %s [-h] [-R [-H | -L | -P]] %s file ...\n",
348 __progname, ischmod ? "mode" : ischflags ? "flags" :
349 ischown ? "owner[:group]" : "group");
350 if (ischown)
351 fprintf(stderr(&__sF[2]),
352 " %s [-h] [-R [-H | -L | -P]] :group file ...\n",
353 __progname);
354 exit(1);
355}