Bug Summary

File:src/sbin/restore/main.c
Warning:line 269, column 10
Potential leak of memory pointed to by 'argv'

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 main.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/sbin/restore/obj -resource-dir /usr/local/lib/clang/13.0.0 -D RRESTORE -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/restore/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/sbin/restore/main.c
1/* $OpenBSD: main.c,v 1.26 2017/01/21 08:31:44 krw Exp $ */
2/* $NetBSD: main.c,v 1.13 1997/07/01 05:37:51 lukem Exp $ */
3
4/*
5 * Copyright (c) 1983, 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 <sys/time.h>
35
36#include <ufs/ffs/fs.h>
37#include <ufs/ufs/dinode.h>
38#include <protocols/dumprestore.h>
39
40#include <err.h>
41#include <paths.h>
42#include <signal.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <string.h>
46#include <unistd.h>
47#include <limits.h>
48
49#include "restore.h"
50#include "extern.h"
51
52int bflag = 0, cvtflag = 0, dflag = 0, vflag = 0, yflag = 0;
53int hflag = 1, mflag = 1, Nflag = 0;
54char command = '\0';
55long dumpnum = 1;
56long volno = 0;
57long ntrec;
58char *dumpmap;
59char *usedinomap;
60ino_t maxino;
61time_t dumptime;
62time_t dumpdate;
63FILE *terminal;
64char *tmpdir;
65
66static void obsolete(int *, char **[]);
67static void usage(void);
68
69int
70main(int argc, char *argv[])
71{
72 int ch;
73 ino_t ino;
74 char *inputdev;
75 char *symtbl = "./restoresymtable";
76 char *p, name[PATH_MAX1024];
77
78 /* Temp files should *not* be readable. We set permissions later. */
79 (void)umask(077);
80
81 if (argc < 2)
1
Assuming 'argc' is >= 2
2
Taking false branch
82 usage();
83
84 if ((inputdev = getenv("TAPE")) == NULL((void *)0) || *inputdev == '\0')
3
Assuming the condition is false
4
Assuming the condition is false
5
Taking false branch
85 inputdev = _PATH_DEFTAPE"/dev/rst0";
86 if ((tmpdir = getenv("TMPDIR")) == NULL((void *)0) || *tmpdir == '\0')
6
Assuming the condition is false
7
Assuming the condition is false
8
Taking false branch
87 tmpdir = _PATH_TMP"/tmp/";
88 if ((tmpdir = strdup(tmpdir)) == NULL((void *)0))
9
Assuming the condition is false
10
Taking false branch
89 err(1, NULL((void *)0));
90 for (p = tmpdir + strlen(tmpdir) - 1; p >= tmpdir && *p == '/'; p--)
11
Assuming 'p' is < 'tmpdir'
91 continue;
92 obsolete(&argc, &argv);
12
Calling 'obsolete'
22
Returned allocated memory via 2nd parameter
93 while ((ch = getopt(argc, argv, "b:cdf:himNRrs:tvxy")) != -1)
23
Assuming the condition is false
24
Loop condition is false. Execution continues on line 150
94 switch(ch) {
95 case 'b':
96 /* Change default tape blocksize. */
97 bflag = 1;
98 ntrec = strtol(optarg, &p, 10);
99 if (*p)
100 errx(1, "illegal blocksize -- %s", optarg);
101 if (ntrec <= 0)
102 errx(1, "block size must be greater than 0");
103 break;
104 case 'c':
105 cvtflag = 1;
106 break;
107 case 'd':
108 dflag = 1;
109 break;
110 case 'f':
111 inputdev = optarg;
112 break;
113 case 'h':
114 hflag = 0;
115 break;
116 case 'i':
117 case 'R':
118 case 'r':
119 case 't':
120 case 'x':
121 if (command != '\0')
122 errx(1,
123 "%c and %c options are mutually exclusive",
124 ch, command);
125 command = ch;
126 break;
127 case 'm':
128 mflag = 0;
129 break;
130 case 'N':
131 Nflag = 1;
132 break;
133 case 's':
134 /* Dumpnum (skip to) for multifile dump tapes. */
135 dumpnum = strtol(optarg, &p, 10);
136 if (*p)
137 errx(1, "illegal dump number -- %s", optarg);
138 if (dumpnum <= 0)
139 errx(1, "dump number must be greater than 0");
140 break;
141 case 'v':
142 vflag = 1;
143 break;
144 case 'y':
145 yflag = 1;
146 break;
147 default:
148 usage();
149 }
150 argc -= optind;
151 argv += optind;
152
153 if (command == '\0')
25
Assuming the condition is false
26
Taking false branch
154 errx(1, "none of i, R, r, t or x options specified");
155
156 if (signal(SIGINT2, onintr) == SIG_IGN(void (*)(int))1)
27
Assuming the condition is false
28
Taking false branch
157 (void)signal(SIGINT2, SIG_IGN(void (*)(int))1);
158 if (signal(SIGTERM15, onintr) == SIG_IGN(void (*)(int))1)
29
Assuming the condition is false
30
Taking false branch
159 (void)signal(SIGTERM15, SIG_IGN(void (*)(int))1);
160 setvbuf(stderr(&__sF[2]), NULL((void *)0), _IOLBF1, 0);
161
162 atexit(cleanup);
163
164 setinput(inputdev);
165
166 if (argc == 0) {
31
Assuming 'argc' is not equal to 0
32
Taking false branch
167 argc = 1;
168 *--argv = ".";
169 }
170
171 switch (command) {
33
'Default' branch taken. Execution continues on line 269
172 /*
173 * Interactive mode.
174 */
175 case 'i':
176 setup();
177 extractdirs(1);
178 initsymtable(NULL((void *)0));
179 runcmdshell();
180 break;
181 /*
182 * Incremental restoration of a file system.
183 */
184 case 'r':
185 setup();
186 if (dumptime > 0) {
187 /*
188 * This is an incremental dump tape.
189 */
190 Vprintfif (vflag) fprintf(stdout(&__sF[1]), "Begin incremental restore\n");
191 initsymtable(symtbl);
192 extractdirs(1);
193 removeoldleaves();
194 Vprintfif (vflag) fprintf(stdout(&__sF[1]), "Calculate node updates.\n");
195 treescan(".", ROOTINO((ufsino_t)2), nodeupdates);
196 findunreflinks();
197 removeoldnodes();
198 } else {
199 /*
200 * This is a level zero dump tape.
201 */
202 Vprintfif (vflag) fprintf(stdout(&__sF[1]), "Begin level 0 restore\n");
203 initsymtable(NULL((void *)0));
204 extractdirs(1);
205 Vprintfif (vflag) fprintf(stdout(&__sF[1]), "Calculate extraction list.\n");
206 treescan(".", ROOTINO((ufsino_t)2), nodeupdates);
207 }
208 createleaves(symtbl);
209 createlinks();
210 setdirmodes(FORCE0x0001);
211 checkrestore();
212 if (dflag) {
213 Vprintfif (vflag) fprintf(stdout(&__sF[1]), "Verify the directory structure\n");
214 treescan(".", ROOTINO((ufsino_t)2), verifyfile);
215 }
216 dumpsymtable(symtbl, (long)1);
217 break;
218 /*
219 * Resume an incremental file system restoration.
220 */
221 case 'R':
222 initsymtable(symtbl);
223 skipmaps();
224 skipdirs();
225 createleaves(symtbl);
226 createlinks();
227 setdirmodes(FORCE0x0001);
228 checkrestore();
229 dumpsymtable(symtbl, (long)1);
230 break;
231 /*
232 * List contents of tape.
233 */
234 case 't':
235 setup();
236 extractdirs(0);
237 initsymtable(NULL((void *)0));
238 while (argc--) {
239 canon(*argv++, name, sizeof name);
240 ino = dirlookup(name);
241 if (ino == 0)
242 continue;
243 treescan(name, ino, listfile);
244 }
245 break;
246 /*
247 * Batch extraction of tape contents.
248 */
249 case 'x':
250 setup();
251 extractdirs(1);
252 initsymtable(NULL((void *)0));
253 while (argc--) {
254 canon(*argv++, name, sizeof name);
255 ino = dirlookup(name);
256 if (ino == 0)
257 continue;
258 if (mflag)
259 pathcheck(name);
260 treescan(name, ino, addfile);
261 }
262 createfiles();
263 createlinks();
264 setdirmodes(0);
265 if (dflag)
266 checkrestore();
267 break;
268 }
269 return (0);
34
Potential leak of memory pointed to by 'argv'
270}
271
272static void
273usage(void)
274{
275
276 (void)fprintf(stderr(&__sF[2]), "usage: %s [-chimRrtvxy] [-b blocksize] [-f file] [-s fileno] [file ...]\n", __progname);
277 exit(1);
278}
279
280/*
281 * obsolete --
282 * Change set of key letters and ordered arguments into something
283 * getopt(3) will like.
284 */
285static void
286obsolete(int *argcp, char **argvp[])
287{
288 int argc, flags;
289 char *ap, **argv, *flagsp, **nargv, *p;
290 size_t len;
291
292 /* Setup. */
293 argv = *argvp;
294 argc = *argcp;
295
296 /* Return if no arguments or first argument has leading dash. */
297 ap = argv[1];
298 if (argc
12.1
'argc' is not equal to 1
== 1 || *ap == '-')
13
Assuming the condition is false
14
Taking false branch
299 return;
300
301 /* Allocate space for new arguments. */
302 if ((*argvp = nargv = calloc(argc + 1, sizeof(char *))) == NULL((void *)0) ||
15
Memory is allocated
16
Assuming the condition is false
18
Taking false branch
303 (p = flagsp = malloc(strlen(ap) + 2)) == NULL((void *)0))
17
Assuming the condition is false
304 err(1, NULL((void *)0));
305
306 *nargv++ = *argv;
307 argv += 2;
308
309 for (flags = 0; *ap; ++ap) {
19
Loop condition is false. Execution continues on line 338
310 switch (*ap) {
311 case 'b':
312 case 'f':
313 case 's':
314 if (*argv == NULL((void *)0)) {
315 warnx("option requires an argument -- %c", *ap);
316 usage();
317 }
318 len = strlen(*argv) + 2 + 1;
319 if ((nargv[0] = malloc(len)) == NULL((void *)0))
320 err(1, NULL((void *)0));
321 nargv[0][0] = '-';
322 nargv[0][1] = *ap;
323 (void)strlcpy(&nargv[0][2], *argv, len-2);
324 ++argv;
325 ++nargv;
326 break;
327 default:
328 if (!flags) {
329 *p++ = '-';
330 flags = 1;
331 }
332 *p++ = *ap;
333 break;
334 }
335 }
336
337 /* Terminate flags. */
338 if (flags
19.1
'flags' is 0
) {
20
Taking false branch
339 *p = '\0';
340 *nargv++ = flagsp;
341 } else {
342 free(flagsp);
343 }
344
345 /* Copy remaining arguments. */
346 while ((*nargv++ = *argv++))
21
Loop condition is false. Execution continues on line 350
347 continue;
348
349 /* Update argument count. */
350 *argcp = nargv - *argvp - 1;
351}